Files
JsonTool/json-mapper-class/README.md
2024-09-27 01:15:47 +08:00

489 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# json-mapper-class
`json-mapper-class` 是类似flutter Json序列化的 **web前端 优雅 解决方案**,用来将接口 json 数据映射到 class 的工具,之后在我们的`TypeScript`项目中,可以通过 **类来为接口返回数据标注类型**,通过修改类属性达到不需要后端修改接口数据字段的情况下,前端来任意定义接口返回字段的效果,解决了实际项目中接口数据与页面深度耦合的过程,并提供其逆过程。
`json-mapper-class` 是一个独立的插件,可以与任何的 `TypeScript` 项目进行深度的集成最好是class语法同时提供了众多的装饰器让你更加**优雅**的去编写 `TypeScript`,请仔细阅读文档。
同时为了方便 `json-mapper-class` 的方法 `toClass` 第二个参数的生成,也是为了避免手动编写`json-mapper-class` **标准类 模版代码** 的过程,本人开发第二个插件简化了过程,插件地址(请自信阅读文档):
> [json-class-interface](https://www.npmjs.com/package/json-class-interface)
下面是一个案例:
```ts
import { property, toClass } from 'json-mapper-class';
class UserModel {
@property('i')
id: number;
@property()
name: string;
}
const userRaw = {
i: 1234,
name: 'name',
};
// 使用 toClass 将 json 转换成 class
const userModel = toClass(userRaw, UserModel);
// 你将获得如下数据
{
id: 1234,
name: 'name',
}
```
# 如何安装
```bash
npm i json-mapper-class --save
```
# 使用例子
## 聚合对象或数组
如果你想转换一个聚合对象,需要提供目标类。如果该对象的某个属性值是数组,则会递归该数组的所有元素(不管层级有多深),自动转换为目标类的实例。
列子:
```ts
class NestedModel {
@property('e', UserModel)
employees: UserModel[];
@typed(UserModel)
@property('u')
user: UserModel;
}
const model = toClass(
{
e: [
{ i: 1, n: 'n1' },
{ i: 2, n: 'n2' },
],
u: {
i: 1,
n: 'name',
}
},
NestedModel,
);
// you will get like this
{
employees: [
{ id: 1, name: 'n1' },
{ id: 2, name: 'n2' },
],
user: {
id: 1,
name: 'name'
}
}
const model = toPlain(
{
employees: [
{ id: 1, name: 'n1' },
{ id: 2, name: 'n2' },
],
user: {
id: 1,
name: 'name'
}
},
NestedModel,
);
// you will get like this
{
e: [
{ i: 1, n: 'n1' },
{ i: 2, n: 'n2' },
],
u: {
i: 1,
n: 'name'
}
}
```
## 其他数据类型转换
```ts
import * as moment from 'moment';
export class EduModel {
@property('i')
id: number;
@property('crt')
@deserialize(value => moment(value).format('YYYY-MM-DD HH:mm:ss'))
createTime: string;
}
```
## 依赖于其他属性值
```ts
class EmailModel {
@property('s')
site: string;
@property('e')
@deserialize((value, _instance, origin) => `${value}@${origin.s}`)
email: string;
}
```
# 方法
## toClass(raw, clazzType, options?) / toClasses(raws, clazzType, options?)
将一个 json 对象映射成一个类实例
- `raw` / `raws` `<Object|Array<Object>>` 一个 josn 对象或者 json 对象数据
- `clazzType` `<Class>` 类的构造函数
- `options?` `<Object>` 配置
- `ignoreDeserializer` `<Boolean>` 当设置为 true 时,不会调用使用 @deserialize 装饰器配置的方法
- `ignoreBeforeDeserializer` `<Boolean>` 当设置为 true 时,不会调用使用 @beforeDeserialize 装饰器配置的方法
- `distinguishNullAndUndefined` `<Boolean>` 当设置为 true 时,区分 null 和 undefined
示例:
```ts
const userRaw = {
i: 1234,
name: 'name',
};
const userRaws = [
{
i: 1000,
name: 'name1',
},
{
i: 2000,
name: 'name2',
},
];
const userModel = toClass(userRaw, UserModel);
const userModels = toClasses(userRaws, UserModel);
```
## toPlain(instance, clazzType, options?) / toPlains(instances, clazzType, options?)
将一个类实例或者 json 对象映射成另外一个 json 对象
- `instance` / `instances` `<Object|Array<Object>>` 一个 json 或类实例或者一个json或类实例组成的数组
- `clazzType` `<Class>` Constructor of the target class
- `options?` `<Object>` 类的构造函数
- `ignoreSerializer` `<Boolean>` 当设置为 true 时,不会调用使用 @serialize 装饰器配置的方法
- `ignoreAfterSerializer` `<Boolean>` 当设置为 true 时,不会调用使用 @afterSerialize 装饰器配置的方法
- `distinguishNullAndUndefined` `<Boolean>` 当设置为 true 时,区分 null 和 undefined
示例:
```ts
const userModel = {
id: 1234,
name: 'name',
};
const userModels = [
{
id: 1000,
name: 'name1',
},
{
id: 2000,
name: 'name2',
},
];
const userRaw = toPlain(userModel, UserModel);
const userRaws = toPlains(userModels, UserModel);
```
# 属性装饰器
调用不同的方法时,这些装饰器的执行顺序:
- `toClass/toClasses`: beforeDeserializer => typed(映射成一个类实例) => deserializer
- `toPlain/toPlains`: serializer => typed(映射成一个对象) => afterSerializer
## property(originalKey?, clazzType?, optional = false)
将一个 key 映射到另外一个 key`n => name`
- `originalKey` `<string>` 被映射的数据 key 如果不传则默认同名
- `clazzType` `<Class>` 自动将该属性的值映射到一个类实例,相当于调用了 `toClass` 方法
- `optional` `<Boolean>` 是否可选
示例:
```ts
class PropertyModel {
@property('i')
id: number;
@property()
name: string;
@property('u', UserModel)
user: UserModel;
@property('t', null, true)
timeStamp: number;
}
const model = toClass({ i: 234, name: 'property', u: { i: 123, n: 'name' } }, PropertyModel);
// 你将获得如下数据
{
id: 234,
name: 'property',
user: {
id: 123,
name: 'name'
}
}
```
## typed(clazzType)
设置一个目标类的构造器,相当于 property 装饰器的第二个参数
- `clazzType` `<Class>` 自动将该属性的值映射到一个类实例,相当于调用了 `toClass` 方法
示例:
```ts
// 与此设置一致 @property('n', UserModel)
class TypedModel {
@typed(UserModel)
@property('u')
user: UserModel;
}
const model = toClass({ u: { i: 123, n: 'name' } }, TypedModel);
// 你将获得如下数据
{
user: {
id: 123,
name: 'name'
}
}
```
## optional()
设置一个属性为可选,相当于 property 装饰器的第三个参数
示例:
```ts
// 与此设置一致 @property('n', null, true)
class OptionalModel {
@optional()
@property('n')
name: string;
}
const model = toClass({}, OptionalModel);
// 你将获得如下数据
{
}
const model = toClass({ n: 'name' }, OptionalModel);
// 你将获得如下数据
{
name: 'name';
}
```
## defaultVal(val)
给当前属性设置默认值
- `val` `<Any>` 要设置的默认值
示例:
```ts
class DefaultValModel {
@defaultVal(0)
@property('i')
id: number;
}
const model = toClass({}, DefaultValModel);
// 你将获得如下数据
{
id: 0;
}
const raw = toPLain({}, DefaultValModel);
// 你将获得如下数据
{
i: 0;
}
```
## serializeTarget()
当调 `toPlain` 进行序列化时,用使用当前数据作为基准
示例:
```ts
class SerializeTargetModel {
@serializeTarget()
@property('n')
name: string;
@property('n')
nick: string;
}
const raw = toPlain(
{
name: 'name',
nick: 'nick',
},
SerializeTargetModel,
);
// 你将获得如下数据
{
n: 'name';
}
```
## beforeDeserialize(beforeDeserializer, disallowIgnoreBeforeDeserializer = false)
`@typed` 调用之前调用
- `beforeDeserializer` `<(value: any, instance: any, origin: any) => any>`
- `value` `<Any>` 该属性在原始对象中的值
- `instance` `<Instance>` 类实例(未完成解析)
- `origin` `<Object>` 原始对象
- `disallowIgnoreBeforeDeserializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@beforeDeserialize` 配置的方法
示例:
```ts
class BeforeDeserializeModel {
@beforeDeserialize((value: any) => JSON.parse(value))
@property('m')
mail: object;
}
toClass(
{
m: '{"id":123}',
},
BeforeDeserializeModel,
);
// 你将获得如下数据
{
mail: { id: 123 },
};
```
## deserialize(deserializer, disallowIgnoreDeserializer =false)
将原始对象序列化成自定义的数组格式,仅在调用 `toClass/toClasses` 时可用
- `deserializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性的值经过 `@beforeDeserialize``@typed` 调用后的结果
- `instance` `<Instance>` 类实例(未完成解析)
- `origin` `<Object>` A raw object
- `disallowIgnoreDeserializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@deserialize` 配置的方法
示例:
```ts
class DeserializeModel {
@deserialize((value: string) => `${value}@xxx.com`)
@property('m')
mail: string;
}
toClass(
{
m: 'mail',
},
DeserializeModel,
);
// 你将获得如下数据
{
mail: 'mail@xxx.com',
};
```
## serialize(serializer, disallowIgnoreSerializer = false)
自定义属性值的序列化方式,仅当调用 `toPlain/toPlains` 时可用
- `serializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性在类实例中的值
- `instance` `<Instance>` 当前类实例
- `origin` `<Object>` 一个json对象未完成序列化
- `disallowIgnoreSerializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@serialize` 配置的方法
Example:
```ts
class SerializeModel {
@serialize((mail: string) => mail.replace('@xxx.com', ''))
@property('e')
mail: string;
}
toPlain(
{
mail: 'mail@xxx.com',
},
SerializeModel,
);
// 你将获得如下数据
{
e: 'mail@xxx.com',
}
```
## afterSerialize(afterSerializer, disallowIgnoreAfterSerializer = false)
Convert a key/value in instance to a target form data, it happened after serializer only
- `afterSerializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性的值经过 `@serializer``@typed` 调用后的结果
- `instance` `<Instance>` 当前类实例
- `origin` `<Object>` 一个json对象未完成序列化
- `disallowIgnoreAfterSerializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@afterSerialize` 配置的方法
示例:
```ts
class AfterSerializeModel {
@afterSerialize((mail: string) => JSON.stringify(mail))
@property('e')
mail: string;
}
toPlain(
{
mail: { id: 1000 },
},
SerializeModel,
);
// 你将获得如下数据
{
e: '{"id":1000}',
};
```