HarmonyOS 鸿蒙Next:【API 11 实践】高效处理HTTP响应:JSON转Class策略探索——class-transformer的实战应用

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

HarmonyOS 鸿蒙Next:【API 11 实践】高效处理HTTP响应:JSON转Class策略探索——class-transformer的实战应用

起因:

在升级至HarmonyOS API 11的过程中,开发者遇到了Object.assign不再适用于数据拷贝的问题,特别是在尝试将JSON数据直接转换为类实例时,发现预设的类属性和方法会被意外丢弃。

https://developer.huawei.com/consumer/cn/forum/topic/0204149169544358375?fid=0109140870620153026

方案:

针对这一挑战,探索了一种更为先进的解决方案,即利用第三方库class-transformer的plainToClassFromExist方法,有效应对JSON到类对象转换的难题,从而优化了API 11环境下应用的开发体验。

优点:

•自动映射与类型安全:避免手动逐个映射JSON键值到类属性,减少出错概率。

•缺失字段处理:即使服务端返回的JSON缺少某些字段,预先定义在model class中的属性(如notPar)和方法(如logCodeStatus())仍能被保留,确保了客户端逻辑的完整性。

•代码精简与一致性:通过面向对象的方式组织数据,使得数据处理逻辑更加条理清晰。

安装:

要开始使用class-transformer,通过OpenHarmony包管理器执行安装命令:ohpm i class-transformer。

示例:

import axios, { AxiosResponse } from @ohos/axios’;
import { plainToClassFromExist } from ‘class-transformer’;

// 定义基础响应类,包含状态码 class BaseResponse { status: number = -1; }

// 定义业务数据类,包含操作码、结果数据及测试字段 class SoulWordsData { code: number = -1; result: SoulWordsDataResult = new SoulWordsDataResult(); notPar: string = ‘xxx’;

logCodeStatus() { console.info(Service Data Code Status: ${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.code}); } }

// 结果数据类,承载具体内容 class SoulWordsDataResult { content: string = ‘’; }

// 综合响应类,继承基础响应并携带具体业务数据 class SoulWords extends BaseResponse { data: SoulWordsData = new SoulWordsData(); }

// 页面组件,负责发起HTTP请求并展示结果 @Entry @Component struct Page47 { @State context: string = ‘’

// 发起HTTP GET请求的方法 fetchHttp(url: string) { axios.get(url) .then((response: AxiosResponse<string>) => { console.info(‘接口响应信息:’); console.info(JSON.stringify(response, null, “–”)) const transformedResponse = plainToClassFromExist(new SoulWords(), response);//第二个参数是object类型,如果你是json字符串,那么需要JSON.pares(xxx) if (transformedResponse.status === 200 && transformedResponse.data.code === 200) { this.context = transformedResponse.data.result.content; } else if (transformedResponse.status !== 200) { this.context = ‘HTTP Layer Exception’; } else { this.context = ‘Business Exception’; } console.info(‘Unmapped Property Test:’, transformedResponse.data.notPar); transformedResponse.data.logCodeStatus(); }) .catch((error: Error) => { console.error(‘Error:’, error); }); }

build() { Column() { Button(‘点击请求接口:正常情况’) .onClick(() => this.fetchHttp(https://api.oioweb.cn/api/SoulWords)) Button(‘点击请求接口:异常情况’) .onClick(() => this.fetchHttp(https://api.oioweb.cn/api/Souxxxxx)) Text(API Response: ${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.context}) } .width(‘100%’) .height(‘100%’) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

打印:

cke_129836.png

cke_131361.png

参考:

【HarmonyOS NEXT】ArkTS 中Json 转Class:https://developer.huawei.com/consumer/cn/forum/topic/0202148667218787203?fid=0109140870620153026

axios三方仓库 :https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Faxios

class-transformer仓库:https://gitee.com/openharmony-tpc/openharmony_tpc_samples/tree/master/class-transformer



关于HarmonyOS 鸿蒙Next:【API 11 实践】高效处理HTTP响应:JSON转Class策略探索——class-transformer的实战应用的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

18 回复

HarmonyOS的超级终端功能让我实现了真正的设备自由,大爱!

现在找不到,返回404是不能使用了吗

确实找不到了,但试了一下还能用。ohpm install class-transformer

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

还有其他方法吗?

当class 是嵌套类,比如

[@Observed](/user/Observed)

class NavigationSetting {

[@Type](/user/Type)(()=>NavigationAction)

left?: NavigationAction[];

[@Type](/user/Type)(()=>NavigationAction)

right?: NavigationAction[];

}

[@Observed](/user/Observed)

class NavigationAction {

type: number = 0;

title?: string;

}

并且class上都添加[@Observed](/user/Observed)之后,

使用const settingObj = plainToInstance(NavigationSetting,JSON.parse(jsonString))方法,

只有第一层对象会被包装成Proxy(按文档的说法[@Observed](/user/Observed)之后类会被会包装成代理,断点时settingObj 显示为Proxy而非Object),里层对象left,right对应数组中的对象还是Object,但是手动new NavigationAction() 是被包装成Proxy,这样[@ObjectLink](/user/ObjectLink)无法被观察到变化,请问这个有解决方案吗?

对于层组太多的,我现在都利用发送通知。 参考:https://developer.huawei.com/consumer/cn/forum/topic/0203148932614687019?fid=0109140870620153026h±/$%-+然后使用this.dArray.splice(index, 1, this.dArray[index]);更新 参考:https://developer.huawei.com/consumer/cn/forum/topic/0202149168419486295?fid=0109140870620153026

HarmonyOS的隐私保护功能做得非常到位,让我对数据安全更加放心。

为什么通过class-transformer 转换后的类还是object? 

JavaScript(以及基于JavaScript的TypeScript)在运行时是一种动态类型语言,它的对象在内存中并不直接携带类型信息,因此当你在控制台查看转换后的对象时,它会默认以普通的JavaScript对象形式展示,即使它实际上是按你的类结构创建的。

这个转换会卡UI线程,在使用Refresh组件  回调接口处理数据类型转换就会卡UI线程

解决了吗。taskjPool解析有@Observed的class会失败

大佬,那如果说我axios请求返回后,我并不知道具体类型呢,我把Axios请求封装了一个api,调用出传入泛型T,
export function Get<T>(path: string, success: (result: BaseResult<T>) => void, params?: object) {
request(path, Method.GET, true, success, params)
}

export async function GetAsync<T>(path: string, params?: object): Promise<BaseResult<T>> {
return await requestAsync<T>(path, Method.GET, true, params)
}
类似这个,那我转换的时候该怎么写



不知道确切的返回类型时,可以使用 class-transformer 库中的 plainToClass 函数来动态地将 JSON 对象转换为对应的类实例。为了实现这一点,你需要根据实际返回的数据类型来确定转换的目标类。 参考:https://developer.huawei.com/consumer/cn/blog/topic/03151854787432021

就是准备通用的 BaseResult 类作为所有 API 响应的基础结构,并且你想定义具体的响应类。其它类去继承

plainToClass第一个参数是ClassConstructor,那不还是需要知道具体类型么

回到顶部