You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:36:19