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
@Component
struct Index {
  @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 | undefined {
      return this.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](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-json#jsonparse):用于解析JSON字符串生成对应ArkTS对象。

【问题分析】

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

点击放大

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

【解决方案】

借助第三方库对JSON解析进行扩展,实现自动类型映射。需要用到的第三方库有以下两个:class-transformerreflect-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;

    getPhotoName(): string | undefined {
      return this.name
    }
  }

  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解析后自动类型映射,确保反序列化后的对象能够调用其方法。


更多关于HarmonyOS鸿蒙Next中JSON解析成对象后,无法判断对象类型和调用对象中的方法该如何处理的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中JSON解析成对象后,无法判断对象类型和调用对象中的方法该如何处理的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,JSON解析成对象后,无法直接判断对象类型和调用对象中的方法

在HarmonyOS鸿蒙Next中,JSON解析后的对象通常是JsonObjectJsonArray,它们属于鸿蒙提供的ohos.utils库中的数据结构,而不是具体的Java或C++类对象。JsonObjectJsonArray是轻量级的数据容器,主要用于存储和操作JSON格式的数据,不具备直接调用方法的能力。

要处理这个问题,可以通过以下方式:

  1. 手动类型转换:根据JSON结构,手动将JsonObjectJsonArray转换为具体的对象类型。例如,如果JSON表示一个用户对象,可以定义一个User类,然后将JsonObject中的数据提取并赋值给User类的实例。

  2. 使用反射:通过反射机制,动态获取对象的类型并调用其方法。鸿蒙系统支持Java的反射机制,可以通过Class.forName()等方法获取类信息,并调用其方法。

  3. 定义统一的接口:如果JSON对象表示的是多种类型的对象,可以定义一个统一的接口,各个具体类实现该接口。解析JSON后,根据类型信息创建对应的对象实例,并通过接口调用方法。

  4. 使用第三方库:可以考虑使用第三方库如GsonJackson,这些库提供了更高级的JSON解析功能,支持将JSON直接映射到具体的Java对象,并保留对象类型信息。

总之,鸿蒙Next中JSON解析后的对象类型判断和方法调用需要结合具体的业务逻辑和代码设计来处理。

回到顶部