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键及其值,该字段被忽略(其他字段可正常保存)。
我有以下几个问题:
- 这是否属于Typegoose的Bug?(即理论上是否应该支持这种场景?)
- 若我的实现方式有误,是否可配置该数组字段以接收任意嵌套对象?还是必须将数据转为字符串(如JSON.stringify)来保存真正的任意对象数据?
- 若无法实现上述需求,正确的做法是构建类型来保存这类嵌套对象到数组中,该如何操作?希望提供类型定义及模型使用的示例。
问题解答
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
相关产品推荐
相关产品推荐

