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

Typegoose中向数组传递任意JSON对象的相关问题咨询

问题描述

我有一个简化的Typegoose模型:

export class SurveyClass extends BaseClass {
  @prop({ required: true, default: '' })
  public description!: string;

  @prop({ required: true, default: [] })
  public questions!: Array<any>;
}

questions数组用于接收任意JSON数据块,例如:

{
  "id": "1869050556234435",
  "type": "feedback",
  "data": "the feedback data",
  "i18n": {
    "fr": {
      "data": "le feedback data"
    }
  }
}

由于这些数据块的类型和数量不固定,且多为深层嵌套结构,我尝试使用Array<any>类型。这种方式基本可行,但当传入如下数据时:

{
  "id": "1869050556234435",
  "type": "feedback",
  "data": "the feedback data",
  "i18n": {}
}

数据库中不会保存i18n键及其值,该字段被忽略(其他字段可正常保存)。

我有以下几个问题:

  1. 这是否属于Typegoose的Bug?(即理论上是否应该支持这种场景?)
  2. 若我的实现方式有误,是否可配置该数组字段以接收任意嵌套对象?还是必须将数据转为字符串(如JSON.stringify)来保存真正的任意对象数据?
  3. 若无法实现上述需求,正确的做法是构建类型来保存这类嵌套对象到数组中,该如何操作?希望提供类型定义及模型使用的示例。

问题解答

1. 是否属于Typegoose的Bug?

这不是Typegoose的Bug,而是底层依赖的Mongoose默认行为导致的。当使用Array<any>时,Typegoose会映射为Mongoose的Mixed类型数组,但Mongoose默认会过滤空对象({})——因为空对象没有可识别的字段类型,会被判定为无效数据而忽略。

2. 如何配置数组字段接收任意嵌套对象?

不需要转成字符串,通过调整字段的prop配置即可解决:

import { prop, getModelForClass, Mixed } from '@typegoose/typegoose';

export class SurveyClass extends BaseClass {
  @prop({ required: true, default: '' })
  public description!: string;

  // 配置为Mixed类型并关闭strict,允许保存任意结构(包括空对象)
  @prop({ 
    required: true, 
    default: [], 
    type: () => Mixed,
    strict: false 
  })
  public questions!: Array<any>;
}

const SurveyModel = getModelForClass(SurveyClass);

strict: false会让Mongoose不对该字段的数据做严格类型校验,从而保留空对象这类特殊结构。如果需要全局生效,也可以在生成模型时设置:

const SurveyModel = getModelForClass(SurveyClass, {
  schemaOptions: {
    strict: false
  }
});

注意全局关闭strict会影响整个模型的所有字段,按需使用。

3. 构建类型保存嵌套对象的正确方式

如果想要保留TypeScript类型提示,同时支持任意嵌套结构,可以定义灵活的自定义类型,结合Mixed类型使用:

步骤1:定义问题类型

// 定义带扩展性的基础问题类型
type BaseQuestion = {
  id: string;
  type: string;
  data: string;
  [key: string]: any; // 允许添加任意额外字段(如i18n)
};

// 也可以更细粒度定义i18n结构
type I18nData = {
  [lang: string]: {
    data: string;
    [key: string]: any;
  };
};

type Question = BaseQuestion & {
  i18n?: I18nData | {}; // 明确允许i18n为空对象
};

步骤2:在模型中使用该类型

export class SurveyClass extends BaseClass {
  @prop({ required: true, default: '' })
  public description!: string;

  @prop({ 
    required: true, 
    default: [], 
    type: () => Mixed,
    strict: false 
  })
  public questions!: Question[]; // 用自定义类型获得类型提示
}

const SurveyModel = getModelForClass(SurveyClass);

这样既保留了代码的类型校验能力,又能确保空对象等任意结构被正确存储到数据库。


内容的提问来源于stack exchange,提问作者drenl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:36:23