NestJS+PostgreSQL存储JSONB遇「必须为JSON字符串」错误排查
NestJS中使用JSONB字段时遇到"content must be a json string"错误的解决方法
问题根源
错误来自DTO中的@IsJSON()装饰器——这个装饰器的作用是验证输入是否为合法的JSON字符串(比如"{\"messages\": [...], \"detail\": \"xxx\"}"格式),但你在Postman中提交的是嵌套JSON对象,并非字符串,因此验证不通过。
解决方案
因为content是结构化嵌套对象,需要使用class-validator的嵌套验证机制,步骤如下:
- 将IContent接口转换为类
TypeScript接口仅在编译时存在,class-validator无法借助接口进行运行时验证,因此需要把接口改成带验证装饰器的类:
import { IsArray, IsString } from 'class-validator'; export class Content { @IsArray() @IsString({ each: true }) // 确保messages数组的每个元素都是字符串 messages: string[]; @IsString() detail: string; }
- 修改CreateUpdateDTO的验证规则
使用@ValidateNested()和@Type()替换原有的@IsJSON(),实现嵌套对象的验证:
import { ValidateNested, Type } from 'class-validator'; import { Content } from './path-to-content-class'; // 替换为你的Content类实际路径 export class CreateUpdateDTO { @ValidateNested() @Type(() => Content) content: Content; }
- 保持实体类配置不变
你的实体类中@Column('jsonb', { nullable: false, default: {} })的配置是正确的,TypeORM会自动将嵌套对象映射到PostgreSQL的JSONB字段。
验证效果
修改完成后,你在Postman中提交的原始JSON请求体:
{ "content": { "messages": ["testing", "testing", "123"], "detail": "some detail" } }
就能正常通过验证并写入数据库的JSONB字段中。
内容的提问来源于stack exchange,提问作者Dora
相关产品推荐
相关产品推荐

