简体   繁体   English

Map json 数组到 typescript object 数组与构造函数

[英]Map json array to typescript object array with constructor

So I have a json array like this:所以我有一个像这样的 json 数组:

[
  {
    "title": "This is the first title",
    "image": "img/first_img.png"
  },
  {
    "title": "This one is the second",
    "image": "img/second_img.png"
  }
]

My goal is to map the simple json array to typescript object array, which is defined as follows.我的目标是将 map 简单的 json 数组转换为 typescript object 数组,其定义如下。

export class GenericField {
  public Required: boolean;
  public Disabled: boolean;

  constructor() {
    this.Required = false;
    this.Disabled = false;
  }
}

export class StringField extends GenericField {
  private readonly _minLength: number | null;
  private readonly _maxLength: number | null;
  private readonly _value: string;

  constructor(
    minLength: number | null,
    maxLength: number | null,
    value: string
  ) {
    super();
    this._minLength = minLength;
    this._maxLength = maxLength;
    this._value = value;
  }
// ...
}

export class UrlField extends GenericField {
  private _url: string;

  constructor(url: string) {
    super();
    this._url = url;
  }

  public get Url(): string {
    return this._url;
  }
}

export class SliderObject {
  public title: StringField;
  public image: UrlField;

  constructor(title: string, image: string) {
    this.title = new StringField(null, null, title);
    this.image = new UrlField(image);
    this.image.Disabled = true;
  }
}

When I map with class-transformer , the objects aren't mapped correctly.当我使用class-transformer map 时,对象未正确映射。 How do I achieve that I can access Required field and Disabled field, which is not present in json.如何实现我可以访问 json 中不存在的Required字段和Disabled字段。

Stackblitz堆栈闪电战

See my StackBlitz example here 在此处查看我的 StackBlitz 示例

It would be like the following (assuming response.data is where the JSON text is).如下所示(假设response.data是 JSON 文本所在的位置)。

const items: Array<{title: string, image: string}> = JSON.parse(response.data)

const sliderObjects = items.map(item =>
    new SliderObject(item['title'], item['image']))

You can come up with your own reviver and conventions in your models to support proper deserialization.您可以在模型中提出自己的恢复器和约定来支持正确的反序列化。

class SliderObject {
  public title: StringField;
  public image: UrlField;

  constructor(title: string, image: string) { /* class initialization */ }

  static fromJSON(data: { image: string; title: string; }): SliderObject {
    return new SliderObject(data.title, data.image);
  }
  static isDeserializableFromJSON(data: any): data is { image: string; title: string; } {
    return data && typeof(data.image) === 'string' && typeof(data.title) === 'string';
  }
}

function jsonReviver(_: string, value: unknown): unknown {
  if (SliderObject.isDeserializableFromJSON(value)) {
    return SliderObject.fromJSON(value);
  }
  return value;
}

console.log(JSON.parse(`[/* array data */]`, jsonReviver));

In the example above I have added to static methods to SliderObject to help with serialization and a custom json reviver function.在上面的示例中,我已将 static 方法添加到 SliderObject 以帮助进行序列化和自定义 json reviver function。 The static methods detect if data create from JSON.parse can be used to create a sliderObject and the other actually creates the new class. static 方法检测从JSON.parse创建的数据是否可用于创建滑块对象,而另一个实际创建新的 class。 The reviver will call the guard method and return a SliderObject if the guard passed.如果守卫通过,reviver 将调用守卫方法并返回一个 SliderObject。

There are lots ways to skin this cat.有很多方法可以给这只猫剥皮。 I personally eschew TypeScript classes in favor of interfaces which I find are more flexible.我个人避免使用 TypeScript 类,而使用我认为更灵活的接口。 Why try to make TypeScript C# or Java?为什么要尝试制作 TypeScript C# 或 Java? By using interfaces, I can largely avoid situations like these.通过使用接口,我可以在很大程度上避免这样的情况。

Please check some updates that I made in order to have your object attributes accessible:请检查我为使您的 object 属性可访问而进行的一些更新:

https://stackblitz.com/edit/new-project-w5b97l?file=src/app/field-definition.ts https://stackblitz.com/edit/new-project-w5b97l?file=src/app/field-definition.ts

A few notes:几点注意事项:

  • The GET request from the slider_object.json file is NOT returning an Observable<SliderObject[]> but an Observable<SliderObjectDTO[]> (or some other name for the interface).来自slider_object.json文件的GET请求返回Observable<SliderObject[]> ,而是返回Observable<SliderObjectDTO[]> (或接口的其他名称)。 An instance of SliderObject has the StringField attribute and the UrlField attribute, while what you are reading from the file are JSON objects ( NOT SliderObject instances) which check the SliderObjectDTO interface, so they will have the title and image properties. SliderObject的实例具有StringField属性和UrlField属性,而您从文件中读取的是检查SliderObjectDTO接口的 JSON 对象(不是SliderObject实例),因此它们将具有titleimage属性。

  • observables should follow this naming convention: observableName$ , so with a $ symbol at the end, thus sliderObjects renamed to sliderObjects$ observables 应该遵循这个命名约定: observableName$ ,所以最后有一个$符号,因此sliderObjects重命名为sliderObjects$

  • class attributes should not start with a capital letter, thus Required renamed to required , Disabled renamed to disabled . class 属性不应以大写字母开头,因此将Required重命名为requiredDisabled重命名为disabled The same thing applies for the properties (getters)同样的事情适用于属性(吸气剂)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM