# json-mapper-class **Repository Path**: bmycode/json-mapper-class ## Basic Information - **Project Name**: json-mapper-class - **Description**: json-mapper-class 是类似flutter Json序列化的 web前端 优雅 解决方案,用来将接口 json 数据映射到 class 的工具,之后在我们的TypeScript项目中,可以通过类来为接口返回标准类型,通过修改类属性达到不需要后端修改接口数据字段的情况下,前端来任意定义接口返回字段的效果,解决了实际项目中接口数据与页面深度耦合的过程,并提供其逆过程。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-10-25 - **Last Updated**: 2023-10-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 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` `>` 一个 josn 对象或者 json 对象数据 - `clazzType` `` 类的构造函数 - `options?` `` 配置 - `ignoreDeserializer` `` 当设置为 true 时,不会调用使用 @deserialize 装饰器配置的方法 - `ignoreBeforeDeserializer` `` 当设置为 true 时,不会调用使用 @beforeDeserialize 装饰器配置的方法 - `distinguishNullAndUndefined` `` 当设置为 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` `>` 一个 json 或类实例,或者一个json或类实例组成的数组 - `clazzType` `` Constructor of the target class - `options?` `` 类的构造函数 - `ignoreSerializer` `` 当设置为 true 时,不会调用使用 @serialize 装饰器配置的方法 - `ignoreAfterSerializer` `` 当设置为 true 时,不会调用使用 @afterSerialize 装饰器配置的方法 - `distinguishNullAndUndefined` `` 当设置为 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` `` 被映射的数据 key, 如果不传则默认同名 - `clazzType` `` 自动将该属性的值映射到一个类实例,相当于调用了 `toClass` 方法 - `optional` `` 是否可选 示例: ```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` `` 自动将该属性的值映射到一个类实例,相当于调用了 `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` `` 要设置的默认值 示例: ```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` `` 该属性在原始对象中的值 - `instance` `` 类实例(未完成解析) - `origin` `` 原始对象 - `disallowIgnoreBeforeDeserializer` `` 默认为 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` `` 该属性的值经过 `@beforeDeserialize` 和 `@typed` 调用后的结果 - `instance` `` 类实例(未完成解析) - `origin` `` A raw object - `disallowIgnoreDeserializer` `` 默认为 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` `` 该属性在类实例中的值 - `instance` `` 当前类实例 - `origin` `` 一个json对象(未完成序列化) - `disallowIgnoreSerializer` `` 默认为 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` `` 该属性的值经过 `@serializer` 和 `@typed` 调用后的结果 - `instance` `` 当前类实例 - `origin` `` 一个json对象(未完成序列化) - `disallowIgnoreAfterSerializer` `` 默认为 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}', }; ```