HarmonyOS 鸿蒙Next JSON解析成对象后,无法判断对象类型和调用对象中的方法该如何处理
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-transformer 和 reflect-metadata 等第三方库,可以实现JSON 解析后自动类型映射,确保反序列化后的对象能够调用其方法。
在处理HarmonyOS鸿蒙Next JSON解析成对象后,若无法判断对象类型和调用对象中的方法,可以采取以下技术方案:
-
使用泛型与反射:在解析JSON时,利用泛型将JSON字符串转换为Map<String, Object>类型,再通过反射机制(如Java的
Class.forName
和Method.invoke
)动态判断对象类型并调用相应方法。 -
JSON库支持:确保使用的JSON解析库(如Gson或Fastjson)支持复杂的对象映射,并配置好TypeToken或TypeReference来保持泛型信息,从而正确解析出对象类型。
-
类型标识字段:在JSON数据中加入一个类型标识字段,解析时首先读取该字段以确定具体类型,然后实例化对应的类并填充数据。
-
多态处理:如果对象体系涉及多态,考虑使用接口或抽象类作为解析目标,结合工厂模式或依赖注入根据类型标识创建具体实现类实例。
-
异常处理:增加异常捕获逻辑,对解析失败或类型不匹配的情况进行妥善处理,避免程序崩溃。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。