HarmonyOS鸿蒙Next中关于请求参数类型的问题

发布于 1周前 作者 sinazl 来自 鸿蒙OS

HarmonyOS鸿蒙Next中关于请求参数类型的问题

  1. 数据类型大概分两种: 基本类型、引用类型
  2. 在发起请求的过程中有时候需要将 json 对象作为参数传入
  3. 当前遇到的问题: 将 Map 对象作为请求的参数传入, 发起请求后, 后端接口好像获取不到数据
  4. 发现问题后执行的操作: 在参数封装进 Map 之前进行打印, 是可以获取到的 在参数封装进 Map 之后 JSON.stringify(map) 输出为 {}
  5. 疑问: 1>. 为什么会出现这种情况 2>. Record 为什么可以解决这个问题
6 回复

以下是相关分析,望采纳,谢谢!

  1. 问题现象分析

    • Map 对象作为请求参数传递时,后端接收不到数据
    • 使用 JSON.stringify(map) 输出为 {}
    • 但参数在封装进 Map 前可以正常打印
  2. 根本原因

    • 2.1 JavaScript/TypeScript 中 Map 的特殊性
      • Map 是一种特殊的键值对集合,不是纯对象
      • 默认的 JSON.stringify() 方法无法正确处理 Map 对象
      • Map 的键可以是任意类型(对象、函数等),而 JSON 标准只支持字符串键
    • 2.2 序列化问题
      1. JSON.stringify 会调用 Map 对象的 toJSON() 方法
      2. 默认 Map 没有实现这个方法,所以返回空对象 {}
      3. 因此传输到后端的就是空对象
  3. 为什么 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 能被正确序列化的原因:
      1. 它是普通对象,符合 JSON 格式标准
      2. 键自动转为字符串
      3. 值如果是可序列化的也会被正确处理
  4. 解决方案

    • 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)); // 正确输出
  5. 最佳实践建议

    • 与后端通信时:
      • 优先使用 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)
          }
        );
      }
  6. 总结

    • 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支持多种参数类型,包括基本类型(如intfloatstring等)、复杂类型(如objectarray)以及自定义类型。开发者需要根据API文档明确指定参数类型,以确保接口调用的正确性。

例如,使用Http模块发送请求时,options参数通常是一个object类型,包含urlmethodheaderdata等字段。data字段可以是stringArrayBufferobject类型,具体取决于请求的内容类型。

在UI组件的事件回调中,参数类型通常由事件类型决定。例如,Button组件的click事件回调函数的参数是一个ClickEvent对象,包含事件相关的信息。

开发者在使用API时,应仔细阅读官方文档,确保参数类型与API要求一致。

在HarmonyOS鸿蒙Next中,请求参数的类型主要取决于API的设计和具体的使用场景。常见的请求参数类型包括:

  1. 基本数据类型:如intfloatdoublebooleanString等,用于传递简单的数值或字符串信息。

  2. 复合数据类型:如JSONObjectJSONArray,用于传递结构化的数据,通常用于网络请求或跨应用通信。

  3. 自定义对象:开发者可以定义自己的类,将多个相关数据封装在一个对象中传递。

  4. 文件类型:如FileInputStream,用于上传文件或处理二进制数据。

  5. 枚举类型:用于传递一组预定义的常量值,确保参数的有效性和一致性。

在编写代码时,应根据API文档明确参数类型,并确保传递的数据类型与API要求一致,以避免运行时错误。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!