如何将JSON数组映射到带构造函数的TypeScript对象数组?
问题描述
现有如下JSON数组:
[ { "title": "This is the first title", "image": "img/first_img.png" }, { "title": "This one is the second", "image": "img/second_img.png" } ]
需要将其映射为自定义TypeScript对象数组,相关类定义如下:
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; } }
使用class-transformer映射时,对象未被正确转换,无法访问JSON中不存在的Required和Disabled字段,请问如何解决?
解决方案
要让class-transformer正确映射并初始化父类的Required、Disabled字段,需要结合装饰器配置和构造函数的正确处理,具体步骤如下:
1. 为类添加自定义转换装饰器
class-transformer默认不会自动触发自定义类的完整构造函数链,需要通过@Transform装饰器手动控制实例化逻辑,确保父类字段被初始化:
import { Type, Transform, plainToInstance } from 'class-transformer'; export class SliderObject { @Transform(({ value }) => new StringField(null, null, value)) public title: StringField; @Transform(({ value }) => { const urlField = new UrlField(value); urlField.Disabled = true; return urlField; }) public image: UrlField; constructor(title: string, image: string) { this.title = new StringField(null, null, title); this.image = new UrlField(image); this.image.Disabled = true; } }
装饰器作用说明
@Transform:直接根据JSON原始值创建对应子类实例,触发StringField/UrlField的构造函数,进而调用父类GenericField的构造函数,自动初始化Required: false、Disabled: false。UrlField的转换逻辑中保留原需求,手动设置Disabled: true。
2. 执行转换并配置参数
调用plainToInstance时,确保开启必要配置以保留类中定义的额外字段:
const jsonData = [ { "title": "This is the first title", "image": "img/first_img.png" }, { "title": "This one is the second", "image": "img/second_img.png" } ]; const sliderObjects = plainToInstance(SliderObject, jsonData, { excludeExtraneousValues: false, // 允许保留类中定义但JSON不存在的字段 enableImplicitConversion: true, // 启用隐式类型转换(可选) }); // 验证字段访问 console.log(sliderObjects[0].title.Required); // 输出 false console.log(sliderObjects[0].image.Disabled); // 输出 true
3. 可选:添加字段暴露装饰器
如果需要更明确地控制字段可见性,可在GenericField的字段上添加@Expose装饰器:
import { Expose } from 'class-transformer'; export class GenericField { @Expose() public Required: boolean; @Expose() public Disabled: boolean; constructor() { this.Required = false; this.Disabled = false; } }
此操作确保class-transformer明确识别这些字段,避免被误过滤。
核心问题解析
之前转换失败的原因是:class-transformer默认仅将JSON属性直接赋值给类实例,不会主动调用自定义类的构造函数,导致父类GenericField中的Required、Disabled字段未被初始化。通过@Transform手动创建实例,可触发完整的构造函数链,解决字段未初始化的问题。
内容的提问来源于stack exchange,提问作者Smilla J.
相关产品推荐
相关产品推荐

