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

NestJS(TypeScript)中GraphQL mutation传JSON对象报类型错误如何解决

问题根因

报错来自两个核心配置和传参错误:

  1. 上层condition字段的GraphQL类型声明错误:你在@Field()装饰器中传入的是TypeScript/JS运行时的全局原生JSON对象,这不是GraphQL可识别的类型,导致schema类型映射异常。
  2. 传参格式错误:你测试时传入的rules是转义后的JSON字符串,GraphQLJSON标量接收的是原生结构化JSON值(对象、数组、字面量值),不需要做字符串序列化转义,传字符串会被判定为类型不匹配。
修复步骤
  • 首先修正condition字段的类型声明
    你的condition本身是已经定义好的RuleConditionInputDto输入类型,不需要声明为JSON标量,修正装饰器配置:
    @Expose()
    @IsOptional()
    @ApiProperty({ type: () => RuleConditionInputDto })
    // 移除错误的JSON类型,指向正确的GraphQL输入类型
    @Field(() => RuleConditionInputDto, { nullable: true })
    condition?: RuleConditionInputDto;
    
  • 注册GraphQLJSON自定义标量
    你使用的GraphQLJSON来自graphql-type-json包,代码优先模式下需要先在NestJS中注册该标量才能被schema识别:
    1. 先安装依赖:npm i graphql-type-json
    2. 新建标量类:
      import { Scalar, CustomScalar } from '@nestjs/graphql';
      import { ValueNode } from 'graphql';
      import GraphQLJSON from 'graphql-type-json';
      
      @Scalar('JSON')
      export class JSONScalar implements CustomScalar<unknown, unknown> {
        parseValue(value: unknown) {
          return GraphQLJSON.parseValue(value);
        }
      
        serialize(value: unknown) {
          return GraphQLJSON.serialize(value);
        }
      
        parseLiteral(ast: ValueNode) {
          return GraphQLJSON.parseLiteral(ast, {});
        }
      }
      
    3. 把JSONScalar加入对应业务模块的providers数组即可。
  • 修正mutation传参格式
    不要对rules字段的值做JSON.stringify转义,直接传入原生结构化对象即可。以GraphQL请求为例:
    操作定义:
    mutation SaveRule($condition: RuleConditionInput) {
      saveRule(condition: $condition) {
        id
      }
    }
    
    变量部分直接传结构化值,不需要转义:
    {
      "condition": {
        "rules": {
          "and": [
            {"<": [{"var": "a.state.temperature"}, 27]},
            {"==": [{"var": "b.state.thermostatMode"}, "cooling"]}
          ]
        },
        "data": {
          "a": { "source": "Entity", "id": "123" },
          "b": { "source": "Entity", "id": "345" }
        }
      }
    }
    
    如果使用Apollo Client等前端客户端,直接将上述对象作为变量传入即可,不需要额外序列化。
常见踩坑提醒
  • @Field()装饰器内传入的类型必须是GraphQL可识别的类型:包括用@ObjectType/@InputType装饰的类、内置标量(String、Int、Boolean等)、已注册的自定义标量,不要传入TS运行时原生对象(比如全局JSON、Object)。
  • JSON标量会自动完成值的序列化/反序列化,传入字符串会被判定为String类型,直接触发Expected value of type "JSON"报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:36:38