[英]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堆栈闪电战
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
实例),因此它们将具有title
和image
属性。
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
重命名为required
, Disabled
重命名为disabled
。 The same thing applies for the properties (getters)同样的事情适用于属性(吸气剂)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.