自定义GraphQLScalarType结合GraphQLNonNull失效,如何实现参数必填?
问题解决:自定义标量配合必填校验失效的处理
你遇到的核心问题是混淆了「自定义标量的格式校验」和「GraphQL参数必填校验」的职责,另外required: true并非GraphQL标准配置,无法实现必填约束。下面是具体的解决步骤:
1. 用GraphQLNonNull正确标记必填参数
GraphQL的必填校验只能通过GraphQLNonNull实现,自定义标量本身只负责校验传入值的格式(比如非空字符串),不处理「是否传入参数」的校验。你之前的写法可能存在语法问题,正确的用法是用GraphQLNonNull包裹自定义标量:
修改你的mutation定义:
addClient: { type: ClientType, args: { // 用GraphQLNonNull包裹自定义标量,标记参数为必填 name: { type: new GraphQLNonNull(NonEmptyString) }, }, resolve(parent, args) { const client = new Client({ name: args.name, }) return client.save() } }
2. 补全自定义标量的parseLiteral方法
你的自定义标量只实现了serialize和parseValue,但当客户端通过查询字面量(而非变量)传参时,会调用parseLiteral方法。补全这个方法可以覆盖所有传参场景,确保空字符串无论哪种方式传入都会被拦截:
修改自定义标量代码:
const { GraphQLScalarType, Kind } = require('graphql'); // 记得引入Kind function validateEmptyStrings(value) { if (typeof value !== 'string') { throw new TypeError('Value must be a string') } if (value === "") { throw new TypeError('Value cannot be empty') } return value } const NonEmptyString = new GraphQLScalarType({ name: 'NonEmptyString', serialize: validateEmptyStrings, parseValue: validateEmptyStrings, parseLiteral(ast) { // 校验AST节点类型是否为字符串 if (ast.kind !== Kind.STRING) { throw new TypeError('Value must be a string') } // 校验字符串非空 if (ast.value === "") { throw new TypeError('Value cannot be empty') } return ast.value }, })
关键说明
required: true不是GraphQL规范中的参数,绝大多数GraphQL实现(如graphql-js、Apollo Server)都不会识别这个配置,必须使用GraphQLNonNull来标记必填参数。- 当参数被
GraphQLNonNull包裹后,客户端如果不传入该参数,GraphQL会直接返回校验错误,不会进入resolve函数,也就不会将字段设为null。 - 自定义标量的三个方法分别对应不同场景:
serialize处理从服务端返回给客户端的值,parseValue处理客户端通过变量传入的值,parseLiteral处理客户端在查询字符串中直接写的字面量值,补全三者才能实现全面校验。
内容的提问来源于stack exchange,提问作者Itakpe Emmanuel
相关产品推荐
相关产品推荐

