JSON 转 Class
2023-05-07 10:43:28

基类

interface  ModelInterface {
  _init: (data: any) => void;
  // 用于映射自定义字段
  _customPropertyMapper: () => Record<string, any>;
  // 用于转换成目标Model
  _containerPropertyGenerateModel: () => Record<string, new (...params: any[]) => any>;
}


export class Model implements ModelInterface {
  _init(data: object) {
    if (!data) return

    const propertyMapper = this.hasOwnProperty("_customPropertyMapper") ? this._customPropertyMapper() : null
    const propertyGenerateModel = this.hasOwnProperty("_containerPropertyGenerateModel") ? this._containerPropertyGenerateModel() : null

    for (const key in data) {
      let propertyKey = key

      if (propertyMapper && propertyMapper[key as string]) {
        propertyKey = propertyMapper[key]
      }

      // @ts-ignore
      let propertyValue = data[key]
      if (propertyGenerateModel && propertyGenerateModel[propertyKey]) {
        const _Model = propertyGenerateModel[propertyKey]
        if (propertyValue instanceof Array) {
          propertyValue = propertyValue.map(((item: any) => new _Model(item)))
        } else {
          propertyValue = new _Model(propertyValue)
        }
      }

      // @ts-ignore
      this[propertyKey] = propertyValue
    }
  }

  _customPropertyMapper: () => Record<string, any> = function() { return {} }
  _containerPropertyGenerateModel: () => Record<string, new (...params: any[]) => any> = function() { return {} }
}

如何使用

class HttpResponseModel extends Model {
  code!: number

  constructor(data: object) {
    super()
    this._init(data)
  }
}

class LoginResponseModel extends HttpResponseModel {
  user!: UserModel

  constructor(data: object) {
    super(data)
    this._init(data)
  }

  _customPropertyMapper = function() {
    return {
      "data": "user"
    }
  }

  _containerPropertyGenerateModel = function() {
    return {
      "user": UserModel
    }
  }
}

class UserModel extends Model {
  id!: number

  constructor(data: object) {
    super()
    this._init(data)
  }
}

const res = new LoginResponseModel({
  code: 200,
  data: {
    id: 1
  }
})

console.log(
  new LoginResponseModel({
    code: 200,
    data: {
      id: 1,
      name: "test"
    }
  })
)

// LoginResponseModel {
//   customPropertyMapper: [Function (anonymous)],
//   containerPropertyGenerateModel: [Function (anonymous)],
//   code: 200,
//   data: { id: 1 },
//   user: UserModel {
//     customPropertyMapper: [Function (anonymous)],
//     containerPropertyGenerateModel: [Function (anonymous)],
//     id: 1
//   }
// }