背景
一个前端项目稳定运行一段时间以后。
突然有一天,后台同学找到你,告诉你原先的Student.name要改成Student.fullName,你崩溃了,一遍遍去查代码,查找Student.name,一遍遍测试,确保修改不会有问题。
终于,你成功把Student.name都改成了Student.fullName。
然而,没过几天,某个一直正常的功能突然不能使用了,你开始调试,发现原先整数类型的age突然变成字符串类型了,你找到后台,后台同学来了一句“前端不做检验吗?”,你心态再一次崩溃了…
思考
下次会改什么字段,下次哪个字段会出问题?(瑟瑟发抖)
有什么办法可以一劳永逸地解决这个问题呢?
有点oop编程语言基础的,马上就会想到,这不就是加个adapter的事吗?很多语言都内置adapter,可是ts没有呀,那咋整?
算了,干脆自己造个轮子
解决方案
自己用ts造个api适配器
废话不多说,直接上成品:type-json-mapper
安装
npm install type-json-mapper --save
装饰器
采用装饰器对类属性进行处理,内置三种装饰器:
@mapperProperty($apiName, type)
基本数据类型使用该装饰器
接收两个参数:
$apiName
:接口字段名
type
:(可选)字段转换类型(可选值:‘string’ | ‘int’ | ‘flot’ | ‘boolean’ | ‘date’ |‘time’ | ‘datetime’)
@deepMapperProperty ($apiName, Class)
自定义类型/数组使用该装饰器
接收两个参数:
$apiName
:接口字段名
Class
:自定义类
@filterMapperProperty($apiName, filterFunc)
接收两个参数:
$apiName:接口字段名
filterFunc:自定义过滤器函数
反序列化
内置两种反序列化函数
deserialize(Clazz, json)
反序列化json对象
接收三个参数:
Clazz:自定义类型
json:待反序列化对象
deserializeArr(Clazz, jsonArr)
反序列化数组
接收三个参数:
Clazz:自定义类型
jsonArr:待反序列化数组
使用示例
首先,我们需要造几个类,给类属性加上type-json-mapper内置的装饰器,不要忘记在构造函数内初始化类属性
import { mapperProperty, deepMapperProperty, filterMapperProperty } from "type-json-mapper";
class Lesson {
@mapperProperty("ClassName")
public name: string;
@mapperProperty("Teacher")
public teacher: string;
@mapperProperty("DateTime", "datetime")
public datetime: string;
constructor() {
this.name = "";
this.teacher = "";
this.datetime = "";
}
}
class Address {
public province: string;
public city: string;
@mapperProperty("full_address")
public fullAddress: string;
constructor() {
this.province = "";
this.city = "";
this.fullAddress = "";
}
}
class Student {
@mapperProperty("StudentID", "string")
public id: string;
@mapperProperty("StudentName", "string")
public name: string;
@mapperProperty("StudentAge", "int")
public age: number;
@filterMapperProperty("StudentSex", (val) => {
const map = { 1: '男生', 2: '女生'};
return map[val];
})
public sex: string;
@deepMapperProperty("Address", Address)
public address?: Address;
@deepMapperProperty("Lessons", Lesson)
public lessons?: Lesson[];
constructor() {
this.id = "";
this.name = "";
this.age = 0;
this.sex = 0;
this.address = undefined;
this.lessons = undefined;
}
}
接口返回数据:
let json = {
StudentID: "123456",
StudentName: "李子明",
StudentAge: "9",
StudentSex: "1",
Address: {
province: "广东",
city: "深圳",
full_address: "xxx小学三年二班",
},
Lessons: [
{
ClassName: "中国上下五千年",
Teacher: "建国老师",
DateTime: 1609430399000,
},
],
};
开始转换:
import { deserialize } from 'type-json-mapper';
try {
const student = deserialize(Student, json);
console.dir(student);
} catch(err) {
console.error(err);
}
结果