鸿蒙开发5.0案例分析:基于class-transformer的对象与JSON相互转换

📝往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)

🚩 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

🚩 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

🚩 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

🚩 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

🚩 记录一场鸿蒙开发岗位面试经历~

📃 持续更新中……


场景一:方法将普通 javascript 对象转换为特定类的实例

解决方案

首先我们先定义一个想要指定的特定的类如下:

User里面包含属性id,fistname,lastname,age,data和它的构造方法,还有特定的方法getName和isAdult。

class User {
  id: number;
  firstName: string;
  lastName: string;
  age: number;
  date?: Date;
  
  constructor() {
    this.id = 0;
    this.firstName = "";
    this.lastName = "";
    this.age = 0;
  }
  
  getName() {
    return this.firstName + ' ' + this.lastName;
  }
  
  isAdult() {
    return this.age > 18 && this.age < 60;
  }
}

我们在前端处理后端传送过来的数据时,经过反序列化转换的对象全是plain(literal) object(普通(字面量)对象),如下,这里我们手动写一个待转换成特定对象的 JavaScript对象(JSON形式)。

interface UserJson {
  id: number,
  firstName: string,
  lastName: string,
  age: number,
  date?: Date
}

const userJson:UserJson = {
  id: 1,
  firstName: "Johny",
  lastName: "Cage",
  age: 27,
  date: new Date()
}

使用class-transform可以直接将收到的userJson字面量对象转换为User实例对象,进而可以使用其中的方法。

使用plainToInstance(将字面量转为类实例,支持数组转换)这个接口来进行转化对应实例。

plainToInstance第一个参数传入特定的实体类,第二个传入需要转换的js对象。

export function test1() {
  // JSON转为对象
  const user: User = plainToInstance(User,userJson);
  log("JSON转对象后输出情况");
  //输出class中的方法
  log(user.getName());
  log(user.isAdult() + "");
}

实现效果:

在项目中使用class-transformer 例子

上面已经说明了class-transformer的最简单用法,现在说一个示例如何在项目中使用。

前端代码:

class User {
  //实体类还是我们刚才的实体User(包含fistname,lastname,age,data,和它的构造方法还有特定的方法getName和isAdult) 这里省略重复代码
}

Request.get({
  baseURL: 'http://xxxxx'
}).then((user: User) => {
  console.log(user)
  console.log(user.username)
  console.log(user.getName())
  console.log(user.isAdult())
})

后端代码:

@Get('/user')
findUser() {
  const user = new User('coder', '12345', 18);
  return user;
}

可以发现立马就报错了:

所以我们需要使用class-transformer的plainToInstance来做修改:

Request.get ({
  baseURL : 'http://xxx'}).then((user : User) => {
  const user1 = plainToInstance(User, user)
  console.log(user1.username)
  console.log(user1.getName())
  console.log(user1.isAdult())
})

立马见效,并且还能调用其中的方法:

场景二:JSON 转对象的时候,控制某些敏感字段不对外暴露

解决方案

使用exclude注解可以解决,还是使用User实体来做演示里面的password属性不想被传到JSON。

class User {
  id: number;
  @Exclude()
  password: string;
  
  constructor(id: number, password: string) {
    this.id = id;
    this.password = password;
  }
}

手动写一个待转换成特定对象的 javascript对象(JSON形式)。

interface UserJson {
  'id': number,
  'password': string
}

如果是传入的字符串我们需要搭配JSON.parse来使用,将字符串转化成JSON格式的UserJson对象,使用plainToInstance来进行转换,由于使用了@Exclude()注解

转换成user对象后password属性也不会被输出。

export function SensitiveJsonToInstanceDemo() {
  log('JSON转对象后输出情况');
  let ss = '{"id":1,"password":"123456"}'
  let oo: UserJson = JSON.parse(ss)
  let user: User = plainToInstance(User,oo)
  log('user_id=' + user.id)
  log('user_password=' + user.password);
}

可见需要控制隐藏的password并不会被输出。

场景三:属性是一些复杂结构体时,实现 json 与对象的互转

解决方案

这里我们定义一个需要转换的User实体类,user的id,name 还有firstSonName,firstSonAge。

class User {
  userId: number;
  userName: string;
  firstSonName: string;
  firstSonAge: number;
  
  constructor(userId: number, userName: string, firstSonName: string, firstSonAge: number) {
    this.userId = userId;
    this.userName = userName;
    this.firstSonName = firstSonName;
    this.firstSonAge = firstSonAge;
  }
}

服务端传一个字符串。

{
  'userId': 1,
  'userName': 'abc',
  'children': [
    {
      'username': 'son1',
      'age': '18'
    },
  {
    'username': 'son2',
    'age': '28'
   }
  ]
}

所以我们设计两个接口:

interface UserJson {
  userId: number;
  userName: string;
  firstSonName: string;
  firstSonAge: number;
}

interface FatherJson {
  userId: number;
  userName: string;
  children: Record<string,string>[]
}

直接使用plainToInstance将fatherjson转换成user对象是获取不到firstSonName,与firstSonAge的属性的,所以我们需要进行一个属性拍平。

export function ComplexJsonToInstanceDemo() {
  //服务器返回的字符串
  let ss = '{"userId":1,"userName":"abc","children":[{"username":"son1","age":"18"},{"username":"son2","age":"28"}]}'
  //将字符串转化成JSON
  let fatherjson: FatherJson = JSON.parse(ss)
  let fs: Record<string,string> = fatherjson.children[0]
  
  //fatherjson转userjson
  let userjson: UserJson = {
    userId: fatherjson.userId,
    userName: fatherjson.userName,
    firstSonName: fs['username'],
    firstSonAge: parseInt(fs['age'])
  }
  
  let user: User = plainToInstance(User,userjson)
  log('user_firstSonName=' + user.firstSonName)
  log('user_firstSonAge=' + user.firstSonAge)
}

实现效果,可看到firstSonName与firstSonAge,已经成功获取。

总结

使用三方库class-transformer搭配JSON的JSON.parse,可以满足类似gson/fastjson绝大部分的需求,更多用法可以参考 https://github.com/typestack/class-transformer 文档。

此外,建议审视设计的类和json是否合理,尽量避免使用复杂的转换。

<think>嗯,用户想在HarmonyOS 5.0开发页面并调用后端云服务器的接口,我需要提供一个示例教程。首先,我需要回忆HarmonyOS的网络请求模块,记得http模块是常用的。根据引用[2]提到的,http模块支持Promise和异步回调,这点很重要。我应该分步骤来,从环境配置到页面布局,再到请求发送和数据处理。 首先,环境配置部分需要检查API版本,确保在module.json5中添加网络权限。用户可能容易忘记权限设置,所以要强调这点。接下来,页面布局可能需要使用ArkUI的组件,比如Column、Text、Button,这些在示例代码里应该体现出来。 然后,网络请求部分,使用@ohos.net.http模块的createHttp方法。要注意示例代码中的URL替换,还有GET和POST请求的不同处理方式。可能需要分别展示两种请求方法,比如先演示GET获取数据,再演示POST提交数据。 数据处理方面,需要将JSON转换对象,这里可以引用[4]提到的class-transformer库,但用户可能不熟悉,所以示例中使用JSON.parse可能更简单。同时,要处理加载状态和错误信息,提升用户体验。 最后,注意事项部分要包括HTTPS、UI更新在主线程、错误处理等,这些都是开发中常见的坑。相关问题部分,需要根据引用中的内容,扩展到性能优化、数据解析、状态管理等方面,帮助用户深入学习。 还要确保代码格式正确,使用ArkTS语法,特别是异步函数和Promise的使用。可能用户对ArkTS还不熟,所以代码要简洁明了,注释清楚。同时,引用文献要正确对应,比如http模块引用[2],数据转换引用[4]。整个回答结构要清晰,步骤分明,让用户能一步步跟着操作。</think>### HarmonyOS 5.0 页面开发后端接口调用示例教程 #### 1. 环境配置权限声明 - **步骤1**:在`module.json5`中添加网络权限: ```json { "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ] } } ``` - **步骤2**:确保API版本≥9(Stage模型)[^2] #### 2. 页面布局开发ArkUI) ```typescript // MainPage.ets @Entry @Component struct MainPage { @State data: string = "" @State loading: boolean = false @State error: string = "" build() { Column() { Text("接口数据:") .fontSize(20) Text(this.data) .margin({top:10}) Button("获取数据") .onClick(() => this.fetchData()) .margin({top:20}) if (this.loading) { LoadingProgress() } if (this.error) { Text(this.error).color(Color.Red) } }.padding(20) } } ``` #### 3. 网络请求实现 ```typescript // 导入HTTP模块 import http from '@ohos.net.http'; // 在MainPage类中添加方法 async fetchData() { this.loading = true; this.error = ""; try { // 1. 创建HTTP对象 let httpRequest = http.createHttp(); // 2. 发起GET请求(示例URL) let response = await httpRequest.request( "https://api.example.com/data", { method: http.RequestMethod.GET, header: {'Content-Type': 'application/json'} } ); // 3. 处理响应 if (response.responseCode === 200) { this.data = JSON.parse(response.result).data; } else { this.error = `请求失败:${response.responseCode}`; } } catch (e) { this.error = `网络错误:${e.message}`; } finally { this.loading = false; } } ``` #### 4. POST请求示例 ```typescript async submitData() { let httpRequest = http.createHttp(); let response = await httpRequest.request( "https://api.example.com/submit", { method: http.RequestMethod.POST, header: {'Content-Type': 'application/json'}, extraData: JSON.stringify({key: "value"}) } ); // 处理响应逻辑同上... } ``` #### 5. 关键注意事项 1. **HTTPS强制要求**:生产环境必须使用HTTPS协议[^2] 2. **UI更新机制**:网络回调中更新UI需通过`@State`驱动 3. **JSON数据处理**:推荐使用`JSON.parse()`/`JSON.stringify()`进行转换[^4] 4. **错误处理**:需捕获网络异常和业务逻辑错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值