HarmonyOS鸿蒙Next中关于请求参数类型的问题
HarmonyOS鸿蒙Next中关于请求参数类型的问题
- 数据类型大概分两种: 基本类型、引用类型
- 在发起请求的过程中有时候需要将 json 对象作为参数传入
- 当前遇到的问题:
将
Map
对象作为请求的参数传入, 发起请求后, 后端接口好像获取不到数据 - 发现问题后执行的操作:
在参数封装进
Map
之前进行打印, 是可以获取到的 在参数封装进Map
之后JSON.stringify(map)
输出为 {} - 疑问:
1>. 为什么会出现这种情况
2>.
Record
为什么可以解决这个问题
以下是相关分析,望采纳,谢谢!
-
问题现象分析
- 将
Map
对象作为请求参数传递时,后端接收不到数据 - 使用
JSON.stringify(map)
输出为{}
- 但参数在封装进
Map
前可以正常打印
- 将
-
根本原因
- 2.1 JavaScript/TypeScript 中
Map
的特殊性Map
是一种特殊的键值对集合,不是纯对象- 默认的
JSON.stringify()
方法无法正确处理Map
对象 Map
的键可以是任意类型(对象、函数等),而 JSON 标准只支持字符串键
- 2.2 序列化问题
JSON.stringify
会调用Map
对象的toJSON()
方法- 默认
Map
没有实现这个方法,所以返回空对象{}
- 因此传输到后端的就是空对象
- 2.1 JavaScript/TypeScript 中
-
为什么
Record
可以解决这个问题- 3.1
Record
类型本质Record<K, V>
是 TypeScript 的一种工具类型:- 它表示一个普通的对象(Plain Object)
- 键类型为
K
,值类型为V
- 本质上等同于
{ [key: K]: V }
- 3.2 与
Map
的区别// Map 示例 const map = new Map<string, any>(); map.set('name', '张三'); map.set('age', 25); JSON.stringify(map); // 输出: {} // Record 示例 const record: Record<string, any> = { name: '张三', age: 25 }; JSON.stringify(record); // 输出: {"name":"张三","age":25}
Record
能被正确序列化的原因:- 它是普通对象,符合 JSON 格式标准
- 键自动转为字符串
- 值如果是可序列化的也会被正确处理
- 3.1
-
解决方案
- 4.1 方案1:转换为普通对象
function mapToObject(map: Map<string, any>): Record<string, any> { const obj: Record<string, any> = {}; map.forEach((value, key) => { obj[key] = value; }); return obj; } // 使用示例 const myMap = new Map<string, any>(); myMap.set('name', '李四'); myMap.set('age', 30); const params = mapToObject(myMap); console.log(JSON.stringify(params)); // 正确输出
- 4.2 方案2:使用
Record
替代Map
// 直接使用 Record 类型 const params: Record<string, any> = { name: '王五', age: 28 }; // 添加属性 params.address = '北京市'; // 发起请求 http.request(/* ... */, { params });
- 4.3 方案3:自定义序列化
// 为 Map 添加 toJSON 方法 class SerializableMap extends Map { toJSON() { return Array.from(this.entries()).reduce((obj, [key, value]) => { obj[key] = value; return obj; }, {} as Record<string, any>); } } // 使用示例 const myMap = new SerializableMap(); myMap.set('name', '赵六'); console.log(JSON.stringify(myMap)); // 正确输出
- 4.1 方案1:转换为普通对象
-
最佳实践建议
- 与后端通信时:
- 优先使用
Record<string, any>
或普通对象 - 避免直接传递
Map/Set
等特殊集合类型
- 优先使用
- 需要复杂键时:
- 如果需要非字符串键,先用
Map
处理 - 传输前转换为普通对象
- 如果需要非字符串键,先用
- 类型安全:
interface RequestParams { name: string; age: number; address?: string; } const params: RequestParams = { name: '张三', age: 25 };
- 网络请求示例:
import http from '@ohos.net.http'; async function postData(url: string, data: Record<string, any>) { const httpRequest = http.createHttp(); return httpRequest.request( url, { method: 'POST', header: { 'Content-Type': 'application/json' }, extraData: JSON.stringify(data) } ); }
- 与后端通信时:
-
总结
Map
不被直接支持:因为 JSON 标准限制和序列化机制Record
是解决方案:因为它本质是普通对象,符合 JSON 格式要求- 实际开发建议:前后端通信使用普通对象/
Record
,复杂数据处理用Map
但传输前转换
更多关于HarmonyOS鸿蒙Next中关于请求参数类型的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
非常感谢你的回复,从中我感觉到了细心,答案非常详细。不过我看到你的答案中有说类型安全问题,是因为 Map 和 Record 中的 key 不确定导致的吗?
Map 的类型安全隐患
```typescript
const map = new Map<any, any>(); // 键和值类型完全无约束
map.set(123, '数字键');
map.set({obj: true}, '对象键'); // 键可以是任意类型!
键类型不可控:Map 允许键为任意类型(甚至对象、函数),但 JSON 仅支持字符串键,强行序列化会丢失数据。
值类型无校验:值可以是任何类型,可能包含无法序列化的内容(如函数、循环引用)。
好的,谢谢,
基本信息
名称:示例
描述:这是一个示例描述。
- 项目1: 值1
- 项目2: 值2
- 项目3: 值3
在HarmonyOS鸿蒙Next中,请求参数类型的问题主要涉及到API调用时的数据传递。鸿蒙Next支持多种参数类型,包括基本类型(如int
、float
、string
等)、复杂类型(如object
、array
)以及自定义类型。开发者需要根据API文档明确指定参数类型,以确保接口调用的正确性。
例如,使用Http
模块发送请求时,options
参数通常是一个object
类型,包含url
、method
、header
、data
等字段。data
字段可以是string
、ArrayBuffer
或object
类型,具体取决于请求的内容类型。
在UI组件的事件回调中,参数类型通常由事件类型决定。例如,Button
组件的click
事件回调函数的参数是一个ClickEvent
对象,包含事件相关的信息。
开发者在使用API时,应仔细阅读官方文档,确保参数类型与API要求一致。