基于class-transformer的对象与JSON相互转换

在攒六便士
发布于 2024-8-1 16:38
浏览
0收藏

场景一:方法将普通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的对象与JSON相互转换-鸿蒙开发者社区

在项目中使用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的对象与JSON相互转换-鸿蒙开发者社区

所以我们需要使用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()) 
})

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

基于class-transformer的对象与JSON相互转换-鸿蒙开发者社区

场景二: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并不会被输出。

基于class-transformer的对象与JSON相互转换-鸿蒙开发者社区

场景三:属性是一些复杂结构体时,实现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相互转换-鸿蒙开发者社区

总结

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

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

分类
已于2024-8-1 16:38:19修改
收藏
回复
举报
回复
    相关推荐