HarmonyOS鸿蒙Next中http发送get请求传参有bool类型时,bool参数不能接收成功

HarmonyOS鸿蒙Next中http发送get请求传参有bool类型时,bool参数不能接收成功

const headers: Record<string, string | undefined> = {
  'Content-Type': 'application/json',
  'X-Auth-Token': token,
  'X-Trace-Id': uuid,
  'User-Agent': encodeURIComponent("Mozilla/5.0 (Linux; Android 12; BRA-AL00 Build/HUAWEIBRA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36"),
  'agent': encodeURIComponent("light/4.113.0/android/BRA-AL00/12/BRA-AL00")
}

console.debug(`http request -> ${method}:${url}\nheaders -> ${JSON.stringify(headers)}\ndata -> ${JSON.stringify(requestData)}`)
let commonParams = await getCommonParams()
requestData?.forEach((value,key)=>{
  commonParams.set(key,value)
})
// map转为record类型
const record = mapToRecord(commonParams)
return httpRequest.request(url, {
  method: method,
  header: headers,
  expectDataType: http.HttpDataType.STRING,
  extraData: record,
}).then((httpResponse: http.HttpResponse) => {
}

这是我写的请求 ,在requestData 里面有一个参数,是bool类型(可以默认不传,但是不传参数得到的结果是少一个数据).

然后请求之后,服务端收不到我传的参数,抓包的时候也发现我传的bool类型没有在传参里面.

最后把bool类型的参数改为 "true"或者"false"这样传入才能正常的得到结果


更多关于HarmonyOS鸿蒙Next中http发送get请求传参有bool类型时,bool参数不能接收成功的实战教程也可以访问 https://www.itying.com/category-93-b0.html

16 回复

【解决方案】

开发者您好,对于http get类方法(GET、OPTIONS、TRACE、CONNECT),extraData里面的内容是会拼接到url中的,但是url不支持直接传输布尔类型,需要应用调用encodeURIComponent()对布尔类型变量进行URL转码,本质上和直接传"true"字符串是一样的,根本原因是URL只支持字符串。

【总结】

extraData支持string、Object、ArrayBuffer三种数据类型,且长度没有限制,根据业务场景extraData入参也有所不同:

  1. 当HTTP请求为POST、PUT等方法时,此字段为HTTP请求的content,以UTF-8编码形式作为请求体。
    • 当’content-Type’为’application/x-www-form-urlencoded’时,请求提交的信息主体数据必须在key和value进行URL转码后(encodeURIComponent/encodeURI),按照键值对"key1=value1&key2=value2&key3=value3"的方式进行编码,该字段对应的类型通常为string。
    • 当’content-Type’为’text/xml’时,该字段对应的类型通常为string。
    • 当’content-Type’为’application/json’时,该字段对应的类型通常为Object。
    • 当’content-Type’为’application/octet-stream’时,该字段对应的类型通常为ArrayBuffer。
    • 当’content-Type’为’multipart/form-data’且需上传的字段为文件时,该字段对应的类型通常为ArrayBuffer。
  2. 当HTTP请求为GET、OPTIONS、DELETE、TRACE、CONNECT等方法时,此字段为HTTP请求参数的补充。开发者需传入Encode编码后的string类型参数,Object类型的参数无需预编码,参数内容会拼接到URL中进行发送。ArrayBuffer类型的参数不会做拼接处理。

更多关于HarmonyOS鸿蒙Next中http发送get请求传参有bool类型时,bool参数不能接收成功的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


我了解到的是

GET 请求的参数通过 URL 的Query String(如?isTest=true&page=1)传递,而 Query String 的本质是纯字符串键值对

  • HTTP 协议本身不支持 bool / 数字等原生数据类型,所有参数值最终都必须转为字符串;
  • 若直接传递 bool 类型(true/false),鸿蒙的 httpRequest 在拼接 URL 参数时,不会自动将其转为字符串,反而会忽略该类型参数,导致抓包看不到、服务端收不到。

期待HarmonyOS能在未来推出更多针对企业用户的解决方案。

你这个最准确,确实是这样的,

可以采纳答复一下么,谢谢~,

开发者您好,请查看如下解决方案:

【解决方案】

可查看发送Http请求时选配信息HttpRequestOptions中extraData属性的描述,其中明确说明当HTTP请求为GET、OPTIONS、TRACE、CONNECT等方法时,此字段为HTTP请求参数的补充。开发者需传入Encode编码后的string类型参数,Object类型的参数无需预编码,参数内容会拼接到URL中进行发送。

该问题中extraData所传参数为record类型数据,则record类型数据键值对中value值需为Encode编码后的string类型参数,不能是boolean类型或者其他类型。

应该是这个方法中,在处理map转record时,把boolean类型的数据给过滤掉了。

const record = mapToRecord(commonParams)

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

布尔类型

布尔类型是编程中最基本的数据类型之一,它只有两个值:truefalse。布尔类型通常用于条件判断和逻辑运算。

布尔值的表示

  • true:表示逻辑上的“真”或“是”。
  • false:表示逻辑上的“假”或“否”。

布尔运算

布尔类型支持多种逻辑运算,包括:

  • 逻辑与(AND):使用 && 运算符,当两个操作数都为 true 时,结果为 true
  • 逻辑或(OR):使用 || 运算符,当至少一个操作数为 true 时,结果为 true
  • 逻辑非(NOT):使用 ! 运算符,将 true 变为 false,将 false 变为 true

布尔类型的应用

布尔类型在编程中广泛应用于:

  • 条件语句(如 ifwhile
  • 逻辑判断
  • 控制程序流程

示例

以下是一个简单的布尔类型示例:

let isTrue = true;
let isFalse = false;

// 逻辑与
console.log(isTrue && isFalse); // 输出: false

// 逻辑或
console.log(isTrue || isFalse); // 输出: true

// 逻辑非
console.log(!isTrue); // 输出: false

布尔类型是编程中不可或缺的一部分,理解和熟练使用布尔类型对于编写高效的代码至关重要。

解决方式:
”const record = mapToRecord(commonParams)“

这个方法转换的时候记得把里面的Boolean加个?,或者加个Boolean | undefined

记录中包含参数

记录中包含参数,这些参数在系统运行过程中被使用和传递。

把mapToRecord和requestData,这两个发出来,我看下。 或者,你把requestData的数据复制一份出来,写个demo测试下mapToRecord这个方法能否正常转换。

import { http } from '@kit.NetworkKit';
import { BusinessError, request, systemDateTime } from '@kit.BasicServicesKit';
import { buffer, util } from '@kit.ArkTS';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { Core, DLogger } from 'core';

const TAG = 'RequestClient'

export interface HttpResponse<T> {
  data: T;
  status: number;
  error: Error | undefined
}

export type HttpPromise<T> = Promise<HttpResponse<T>>;

export class RequestClient {
  static getBaseUrl(): string {
    return Core.getHost()
  }

  static getRequestUrl(path: string, baseUrl?: string): string {
    return `${baseUrl ?? RequestClient.getBaseUrl()}${path}`
  }

  static async request(path: string, method: http.RequestMethod, requestData?: Map<string, Object>,
    baseUrl?: string): Promise<HttpPromise<object>> {
    const httpRequest = http.createHttp()
    const token = ''
    const url = RequestClient.getRequestUrl(path, baseUrl)
    const uuid = util.generateRandomUUID(false)
    const headers: Record<string, string | undefined> = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'X-Auth-Token': token,
      'X-Trace-Id': uuid,
      // 'User-Agent': encodeURIComponent("Mozilla/5.0 (Linux; Android 12; BRA-AL00 Build/HUAWEIBRA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36"),
      'agent': encodeURIComponent("light/4.113.0/android/BRA-AL00/12/BRA-AL00")
    }

    DLogger.debug(`http request -> ${method}:${url}\nheaders -> ${JSON.stringify(headers)}\ndata -> ${JSON.stringify(requestData)}`)
    let commonParams = await RequestClient.getCommonParams()
    requestData?.forEach((value, key) => {
      commonParams.set(key, value)
    })
    const record = RequestClient.mapToRecord(commonParams)
    DLogger.debug(`http request record -> ${JSON.stringify(record)}`)

    return httpRequest.request(url, {
      method: method,
      header: headers,
      expectDataType: http.HttpDataType.STRING,
      extraData: record
    }).then((httpResponse: http.HttpResponse) => {
      console.info('Result type:' + httpResponse.resultType); // 验证实际类型

      DLogger.debug(`http response -> ${method}:${url}\n${JSON.stringify(httpResponse)}`)
      if (httpResponse.responseCode === http.ResponseCode.OK) {
        return Promise.resolve(JSON.parse(httpResponse.result.toString()))
      } else {
        return Promise.reject(httpResponse.responseCode)
      }
    }).catch((err: BusinessError) => {
      DLogger.debug(`http error:${JSON.stringify(err)}`);
      return Promise.reject(err)
    }).finally(() => {
      httpRequest.destroy()
    })
  }

  static get(path: string, requestData?: Map<string, Object>,
    baseUrl?: string): Promise<HttpPromise<object>> {
    return RequestClient.request(path, http.RequestMethod.GET, requestData, baseUrl)
  }

  static post(path: string, requestData?: Map<string, Object>,
    baseUrl?: string): Promise<HttpPromise<object>> {
    return RequestClient.request(path, http.RequestMethod.POST, requestData, baseUrl)
  }

  static mapToRecord<K extends string, V>(map: Map<K, V>): Record<K, V> {
    const result: Record<K, V> = {} as Record<K, V>;
    map.forEach((value, key) => {
      result[key] = value;
    });
    return result;
  }

  static async getCommonParams(): Promise<Map<string, Object>> {
    const map = new Map<string, Object>()
    map.set("app_id", "light")
    map.set("timestamp", RequestClient.getCurrentStamp().toString())
    map.set("lang", "zh-Hans")
    map.set("device", "mobile")
    map.set("os", "Android")
    map.set("platform", "light")
    map.set("sdk_version", "2.2.10")
    map.set("version", "88.4.3")
    map.set("terminal", "app")

    // map.set("offset", "0")
    // map.set("limit", "5")
    map.set("system_model", "BRA-AL00")
    return map
  }

  static getCurrentStamp(): number {
    let time = 0
    try {
      time = systemDateTime.getTime(true) / 1000000
    } catch (e) {
      let error = e as BusinessError;
      DLogger.error(`Failed to get time. message: ${error.message}, code: ${error.code}`);
    }
    return time
  }
}

有可能是在你进行各种对象转换的时候,变量类型不匹配导致的;感觉像是有个转换的地方把类型定义成字符串了,跟bool对不上,转换就出错忽略掉了

在HarmonyOS Next中,使用HTTP发送GET请求时,若参数包含bool类型,需将其转换为字符串格式。系统不会自动将bool值序列化为"true"/"false"字符串。建议使用encodeURIComponent()对参数值进行编码处理,确保传输正确。

在HarmonyOS Next的HTTP请求中,布尔(bool)类型参数确实需要特殊处理。根据你的代码和描述,问题出在extraData字段的序列化上。

核心原因: http.request方法中的extraData字段(用于GET请求的查询参数)在底层进行URL编码和拼接时,对布尔值的处理可能不符合预期。布尔值truefalse在转换为字符串时,可能被直接忽略或未正确编码,导致参数无法被服务端识别。

解决方案: 在将参数传递给extraData之前,显式地将所有布尔值转换为字符串。这是最可靠的方法。

根据你的代码,可以在mapToRecord函数中或之前进行转换。一个简单的修改示例如下:

requestData?.forEach((value, key) => {
  // 关键处理:如果值是布尔类型,将其转换为字符串 'true' 或 'false'
  let processedValue = value;
  if (typeof value === 'boolean') {
    processedValue = value.toString(); // 或者 String(value)
  }
  commonParams.set(key, processedValue);
});

解释:

  1. 类型检查:使用typeof value === 'boolean'判断参数是否为布尔类型。
  2. 显式转换:通过toString()String()方法将布尔值转换为明确的字符串"true""false"
  3. 确保传输:转换后的字符串值会作为普通的查询参数值被正确编码和附加到URL之后(例如?key=true),服务端即可正常接收。

你最后将参数改为"true""false"字符串能成功,也验证了这个根本原因。在HTTP GET请求的查询字符串中,所有参数本质上都是字符串形式传输的,显式进行类型转换可以避免底层序列化的不确定性。

回到顶部