HarmonyOS 鸿蒙Next JSON解析成对象后,无法判断对象类型和调用对象中的方法该如何处理

发布于 1周前 作者 itying888 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next JSON解析成对象后,无法判断对象类型和调用对象中的方法该如何处理

【 问题描述】

在处理 JSON 字符串时,使用 JSON.parse(json: string) 解析 JSON 对象,但无法调用解析得到的对象中的方法,尝试调用时会报错:TypeError: is not callable。

报错示例图如下:

问题代码如下:

  • pages/Index.ets(展示页面)

    import { JSONTools } from'../utils/JSONTools'
     import { JSON } from'@kit.ArkTS'
     [@Entry](/user/Entry)
     [@Component](/user/Component)
     struct Index {
       [@State](/user/State) result: string =""
    

    build() { Column() { TextArea({ text:this.result }) .enabled(false) .width(“100%”) .height(“50%”) Button(“test”) .onClick(() =>this.testButtonHandler()) } .width(‘100%’) .height(‘100%’) }

    testButtonHandler() { // 调用JSON解析工具获取JSON中的数据 this.result=JSON.stringify(JSONTools.getPhotoFiles()) } }

  • utils/JSONTools.ets(JSON解析工具)

    import { JSON } from '@kit.ArkTS';
    

    export namespace JSONTools { const albumJson = ‘{“id”: 1, “name”: “test”, “photos”: [{“id”: 11, “name”: “kkk.png”}, {“id”: 112, “name”: “fff.txt”}]}’

    // 相册类,包含一个Photo数组类型的成员 class Album { id?: number; name?: string; photos: Photo[] = []; }

    // 照片类 class Photo { id?: number; name?: string;

    getPhotoName(): string | <span class="hljs-literal"><span class="hljs-literal">undefined</span></span> {
      <span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.name
    }
    

    }

    export function getPhotoFiles(): string[] { let album = JSON.parse(albumJson) as Album if (album && album.photos && album.photos.length > 0) { // 通过map操作获取photos数组中每个对象的name属性 return album.photos.flatMap(photo => photo.getPhotoName()!) } return [] } }

【 背景知识】

@ohos.util.json.parse:用于解析 JSON 字符串生成对应 ArkTS 对象或 null。

【问题分析】

通过调试发现,JSON.parse仅反序列化了对象的数据结构,并不支持映射到具体的类型,因此在调用具体的方法时会报错。通过如下调试截图可以看到转换之后的对象类型均为TypeScript的基本类型:

此处仅使用ArkTS的JSON工具进行转换是不够的,还需要借助class-transformer等三方库才能够实现到具体类型的转换和映射。

【解决方案】

借助第三方库对 JSON 解析进行扩展,实现自动类型映射。需要用到的第三方库有以下两个:_class-transformer_和 _reflect-metadata_。

使用 class-transformer 可以对 JSON 反序列化的对象进行自动转换和映射。同时也需要 reflect-metadata 提供运行时注解的能力,该第三方库直接 import 即可。

(1)在当前module下执行ohpm install命令安装所需的依赖:

ohpm install class-transformer
 ohpm install reflect-metadata

(2)修改 /utils/JSONTools.ets 代码如下:

// Developer Beta2版本后Type类型会与SDK中的Type类型冲突导致编译报错,此处需要重命名
import { Type as JsonType, plainToClass } from 'class-transformer';
import "reflect-metadata";
import { JSON } from '@kit.ArkTS';

export namespace JSONTools { const albumJson = ‘{“id”: 1, “name”: “test”, “photos”: [{“id”: 11, “name”: “kkk.png”}, {“id”: 112, “name”: “fff.txt”}]}’

// 相册类,包含一个Photo数组类型的成员 class Album { id?: number; name?: string; // 自定义类型的成员需要添加装饰器进行映射才能正常转换 @JsonType(() => Photo) photos: Photo[] = []; }

// 照片类 class Photo { id?: number; name?: string;

</span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getPhotoName</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function">: </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">string</span></span></span><span class="hljs-function"> | </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">undefined</span></span></span><span class="hljs-function"> {
  </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">return</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">this</span></span></span><span class="hljs-function">.</span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">name</span></span></span><span class="hljs-function">
}

}

export function getPhotoFiles(): string[] { // 通过JSON.parse进行反序列化,再用plainToClass进行类型转换 let album = plainToClass(Album, JSON.parse(albumJson) as Album) if (album && album.photos && album.photos.length > 0) { // 通过map操作获取photos数组中每个对象的name属性 return album.photos.flatMap(photo => photo.getPhotoName()!) } return [] } }

【 总结】

在 ArkTS 中进行 JSON 反序列化时,数据类型的信息会丢失,这导致解析后的对象无法调用其方法。

仅使用 JSON.parse 无法实现类型的自动映射,但可以通过引入第三方库来实现自动转换和映射类型。通过引入 class-transformerreflect-metadata 等第三方库,可以实现JSON 解析后自动类型映射,确保反序列化后的对象能够调用其方法。

1 回复

在处理HarmonyOS鸿蒙Next JSON解析成对象后,若无法判断对象类型和调用对象中的方法,可以采取以下技术方案:

  1. 使用泛型与反射:在解析JSON时,利用泛型将JSON字符串转换为Map<String, Object>类型,再通过反射机制(如Java的Class.forNameMethod.invoke)动态判断对象类型并调用相应方法。

  2. JSON库支持:确保使用的JSON解析库(如Gson或Fastjson)支持复杂的对象映射,并配置好TypeToken或TypeReference来保持泛型信息,从而正确解析出对象类型。

  3. 类型标识字段:在JSON数据中加入一个类型标识字段,解析时首先读取该字段以确定具体类型,然后实例化对应的类并填充数据。

  4. 多态处理:如果对象体系涉及多态,考虑使用接口或抽象类作为解析目标,结合工厂模式或依赖注入根据类型标识创建具体实现类实例。

  5. 异常处理:增加异常捕获逻辑,对解析失败或类型不匹配的情况进行妥善处理,避免程序崩溃。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。

回到顶部