npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

json-mapper-class

v1.0.2

Published

Json Mapper To Class

Downloads

10

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

下面是一个案例:

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',
}

如何安装

npm i json-mapper-class --save

使用例子

聚合对象或数组

如果你想转换一个聚合对象,需要提供目标类。如果该对象的某个属性值是数组,则会递归该数组的所有元素(不管层级有多深),自动转换为目标类的实例。

列子:

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'
  }
}

其他数据类型转换

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;
}

依赖于其他属性值

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

示例:

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

示例:

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> 是否可选

示例:

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 方法

示例:

// 与此设置一致 @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 装饰器的第三个参数

示例:

// 与此设置一致 @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> 要设置的默认值

示例:

class DefaultValModel {
  @defaultVal(0)
  @property('i')
  id: number;
}

const model = toClass({}, DefaultValModel);
// 你将获得如下数据
{
  id: 0;
}

const raw = toPLain({}, DefaultValModel);
// 你将获得如下数据
{
  i: 0;
}

serializeTarget()

当调 toPlain 进行序列化时,用使用当前数据作为基准

示例:

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 配置的方法

示例:

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 配置的方法

示例:

class DeserializeModel {
  @deserialize((value: string) => `${value}@xxx.com`)
  @property('m')
  mail: string;
}

toClass(
  {
    m: 'mail',
  },
  DeserializeModel,
);

// 你将获得如下数据
{
  mail: '[email protected]',
};

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:

class SerializeModel {
  @serialize((mail: string) => mail.replace('@xxx.com', ''))
  @property('e')
  mail: string;
}

toPlain(
  {
    mail: '[email protected]',
  },
  SerializeModel,
);

// 你将获得如下数据
{
  e: '[email protected]',
}

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 配置的方法

示例:

class AfterSerializeModel {
  @afterSerialize((mail: string) => JSON.stringify(mail))
  @property('e')
  mail: string;
}

toPlain(
  {
    mail: { id: 1000 },
  },
  SerializeModel,
);

// 你将获得如下数据
{
  e: '{"id":1000}',
};