【问题标题】:GraphQL - how to specify maximum String lengths in schemaGraphQL - 如何在模式中指定最大字符串长度
【发布时间】:2020-09-11 17:47:10
【问题描述】:

我想告诉 GraphQL 我的“序列号”字段是一个长度在 1 到 20 个字符之间的字符串。我知道用!在架构中将字段设为必填,但我可以告诉 GraphQL 还有一个最大字段长度吗?

如果我为必填的字符串字段传入一个空值,GraphQL 将不会接受它。我希望它在传递一个比最大允许长度长的字符串时表现相同。

我已经研究过两种方法:1) 在 schema.graphql 文件中的字段定义中添加一个“maxlength”属性。或 2) 创建一个新类型并为其分配最大长度。

我找不到有关如何操作的任何信息。有可能吗?

【问题讨论】:

    标签: graphql


    【解决方案1】:

    你可以使用指令:

    directive @length(max: Int!) on FIELD_DEFINITION
    
    input Payload {
      name: String! @length(max: 50)
    }
    

    【讨论】:

      【解决方案2】:

      graphql(类型)定义中没有这种类型的规范。

      您可以使用指令,但并非所有 graphql 服务器都支持(且未标准化)它们 - 留给特定的实施详细信息 - 检查您的服务器文档。 p>

      对于单个字段您可以简单地在突变解析器中应用此逻辑 - 如果不满足条件(输入字符串长度在 1 到 20 之间)则抛出错误。

      【讨论】:

        【解决方案3】:

        这可以使用 GraphQL 自定义类型来实现。 您可以为所需的每个最大长度定义一个类型:

        StringMaxLenTypes.js:

        const logToConsoleToHelpMeUnderstand = false;
        const { GraphQLScalarType, Kind } = require('graphql');
        const parseStringMaxLenType = (value,maxLength) => {
          logToConsoleToHelpMeUnderstand && console.log('Checking variable passed to a query is a string and max ' + maxLength + 'chars',value)
          if (typeof value === 'string') {
            if (value.length <= maxLength) {
              return value;
            } else {
              throw new Error('parseCi' + maxLength + 'Type: String must not be more that ' + maxLength + ' characters. It is ' + value.length + ' characters');
            }
          } else {
            throw new Error('parseCi' + maxLength + 'Type: value must be of type String. It is of type \'' + typeof value + '\'');
          }
        }
        const parseStringMaxLen20Type = value => { return parseStringMaxLenType(value, 20) };
        const parseStringMaxLen25Type = value => { return parseStringMaxLenType(value, 25) };
        const parseStringMaxLen50Type = value => { return parseStringMaxLentype(value, 50) };
        const parseStringMaxLen255Type = value => { return parseStringMaxLentype(value, 255) };
        const parseStringMaxLen500Type = value => { return parseStringMaxLentype(value, 500) };
        
        
        const serializeStringMaxLenType = (value, maxLength) => {
          /** the serialize methods are called when data is going to be sent to the client. This can return anything
           * of any type, as it will end up as JSON, but we check what is coming back from the database is a string 
           * and not too long.
           */
          logToConsoleToHelpMeUnderstand && console.log(`Checking value '${value}' is at most ${maxLength} chars before serialising for output from graphQL to a client (the OCCP gateway is the client)`);
          if (typeof value === 'string') {
            if (value.length <= maxLength) {
              return value;
            } else {
              throw new Error('serializeCi' + maxLength + 'Type: String must not be more that ' + maxLength + ' characters. It is ' + value.length + ' characters');
            }
          } else {
            throw new Error('serializeCi' + maxLength + 'Type: value must be of type String. It is of type \'' + typeof value + '\'');
          }
        };
        const serializeStringMaxLen20Type = (value) => { return serializeStringMaxLenType(value,20) };
        const serializeStringMaxLen25Type = (value) => { return serializeStringMaxLenType(value,25) };
        const serializeStringMaxLen50Type = (value) => { return serializeStringMaxLenType(value,50) };
        const serializeStringMaxLen255Type = (value) => { return serializeStringMaxLenType(value,255) };
        const serializeStringMaxLen500Type = (value) => { return serializeStringMaxLenType(value,500) };
        
        const parseLiteralStringMaxLenType = (ast, maxLength) => {
          logToConsoleToHelpMeUnderstand && console.log('checking Abstract Syntax Tree value (these come from parameters in GraphQL queries) is not more than ' + maxLength + ' chars long',ast);
          // For input payload i.e. for mutation. ast stands for abstract syntax tree, which is the type of 
          if (ast.kind === Kind.STRING) {
          // Note the parseStringMaxLenType function throws errors, or returns a valid value, so there is no need to throw errors here.
            return parseStringMaxLenType(ast.value, maxLength)
          } else {
            throw new Error()
          }
        };
        
        const parseLiteralStringMaxLen20Type = (ast) => { return parseLiteralStringMaxLenType(ast, 20) }
        const parseLiteralStringMaxLen25Type = (ast) => { return parseLiteralStringMaxLenType(ast, 25) }
        const parseLiteralStringMaxLen50Type = (ast) => { return parseLiteralStringMaxLenType(ast, 50) }
        const parseLiteralStringMaxLen255Type = (ast) => { return parseLiteralStringMaxLenType(ast, 255) }
        const parseLiteralStringMaxLen500Type = (ast) => { return parseLiteralStringMaxLenType(ast, 500) }
        
        const StringMaxLen20Type = new GraphQLScalarType({
          name: 'StringMaxLen20Type',
          description: 'String up to 20 Chars',
          serialize: serializeStringMaxLen20Type,
          parseValue: parseStringMaxLen20Type,
          parseLiteral: parseLiteralStringMaxLen20Type,
        });
        
        const StringMaxLen25Type = new GraphQLScalarType({
          name: 'StringMaxLen25Type',
          description: 'String up to 25 Chars',
          serialize: serializeStringMaxLen25Type,
          parseValue: parseStringMaxLen25Type,
          parseLiteral: parseLiteralStringMaxLen25Type,
        });
        
        const StringMaxLen50Type = new GraphQLScalarType({
          name: 'StringMaxLen50Type',
          description: 'String up to 50 Chars',
          serialize: serializeStringMaxLen50Type,
          parseValue: parseStringMaxLen50Type,
          parseLiteral: parseLiteralStringMaxLen50Type,
        });
        
        const StringMaxLen255Type = new GraphQLScalarType({
          name: 'StringMaxLen255Type',
          description: 'String up to 255 Chars',
          serialize: serializeStringMaxLen255Type,
          parseValue: parseStringMaxLen255Type,
          parseLiteral: parseLiteralStringMaxLen255Type,
        });
        
        const StringMaxLen500Type = new GraphQLScalarType({
          name: 'StringMaxLen500Type',
          description: 'String up to 500 Chars',
          serialize: serializeStringMaxLen500Type,
          parseValue: parseStringMaxLen500Type,
          parseLiteral: parseLiteralStringMaxLen500Type,
        });
        
        module.exports = {StringMaxLen20Type, StringMaxLen25Type, StringMaxLen50Type, StringMaxLen255Type, StringMaxLen500Type };
        

        然后你需要在你的 grapql.shema 中定义这些类型 schema.graphql:

        scalar StringMaxLen20Type
        scalar StringMaxLen25Type
        scalar StringMaxLen50Type
        scalar StringMaxLen255Type
        scalar StringMaxLen500Type
        type YourOtherTypes {
          id: ID!
          canUseAboveTypesLikeThis: StringMaxLen50Type
        }
        

        并将它们导入您的 resolvers.js,并在传递给您的 graphQL 服务器的解析器对象中定义它们: 解析器.js:

        ...
        ...
        const {StringMaxLen20Type, StringMaxLen25Type, StringMaxLen50Type, StringMaxLen255Type, StringMaxLen500Type } = require('StringMaxLenTypes.js');```
        ...
        module.exports = {
        Query: {...},
        Mutation: {...},
        StringMaxLen20Type,
        StringMaxLen25Type,
        StringMaxLen50Type,
        StringMaxLen255Type,
        StringMaxLen500Type
        

        然后,这将应用同样的严格检查,即 GraphQL 将其所有数据类型执行到最大长度。

        【讨论】:

        • 带有指令,您可以使用任何/动态长度
        • 感谢@xadm,但我选择不使用指令,因为我读到它们不是 GraphQL 标准的一部分,因此依赖于实现。这是你的理解吗?
        • 对一个字段应用一些指令与定义数千种可能的类型?类型对于 api 消费者来说看起来很难看?您的解决方案同样基于实现 - 移动到其他服务器时需要重新创建
        • ... 和指令在 graphql 规范中
        • @xadm 你是对的,在当前版本的规范中提到了指令:spec.graphql.org/June2018/#sec-Language.Directives。工作草案详细说明:“GraphQL 实现应该提供@skip@include 指令。”和“必须提供@deprecated..”。它说我们“可能会提供额外的指令”,但我不认为这意味着 @length 将在所有兼容的服务器中实施。
        猜你喜欢
        • 2018-05-21
        • 1970-01-01
        • 1970-01-01
        • 2015-05-03
        • 2016-11-23
        • 2019-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多