HarmonyOS 鸿蒙Next:【API 11 实践】高效处理HTTP响应:JSON转Class策略探索——class-transformer的实战应用
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>
打印:
…
参考:
【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 联系官网客服。
HarmonyOS的超级终端功能让我实现了真正的设备自由,大爱!
确实找不到了,但试了一下还能用。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对象形式展示,即使它实际上是按你的类结构创建的。
建议使用TaskPool处理。参考:https://developer.huawei.com/consumer/cn/blog/topic/03156191575556003
解决了吗。taskjPool解析有@Observed的class会失败
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,那不还是需要知道具体类型么