首页 文章

GraphQL Blackbox /“任何”类型?

提问于
浏览
13

是否可以指定GraphQL中的字段应该是黑盒子,类似于Flow具有“任何”类型的方式?我的架构中有一个字段应该能够接受任意值,可以是String,Boolean,Object,Array等 .

3 回答

  • 7

    我've come up with a middle-ground solution. Rather than trying to push this complexity onto GraphQL, I'选择在场上设置之前使用 String 类型和 JSON.stringify 我的数据 . 所以一切都得到了字符串化,后来在我的应用程序中,当我需要使用这个字段时,我得到了返回所需对象/数组/布尔值等的结果 .

  • 7

    @ mpen的答案很棒,但我选择了更紧凑的解决方案:

    const { GraphQLScalarType } = require('graphql')
    const { Kind } = require('graphql/language')
    
    const ObjectScalarType = new GraphQLScalarType({
      name: 'Object',
      description: 'Arbitrary object',
      parseValue: (value) => {
        return typeof value === 'object' ? value
          : typeof value === 'string' ? JSON.parse(value)
          : null
      },
      serialize: (value) => {
        return typeof value === 'object' ? value
          : typeof value === 'string' ? JSON.parse(value)
          : null
      },
      parseLiteral: (ast) => {
        switch (ast.kind) {
          case Kind.STRING: return JSON.parse(ast.value)
          case Kind.OBJECT: throw new Error(`Not sure what to do with OBJECT for ObjectScalarType`)
          default: return null
        }
      }
    })
    

    然后我的解析器看起来像:

    {
      Object: ObjectScalarType,
      RootQuery: ...
      RootMutation: ...
    }
    

    我的 .gql 看起来像:

    scalar Object
    
    type Foo {
      id: ID!
      values: Object!
    }
    
  • 5

    是 . 只需创建一个允许任何内容的新 GraphQLScalarType .

    这是我写的一个允许对象 . 您可以稍微扩展一下以允许更多的根类型 .

    import {GraphQLScalarType} from 'graphql';
    import {Kind} from 'graphql/language';
    import {log} from '../debug';
    import Json5 from 'json5';
    
    export default new GraphQLScalarType({
        name: "Object",
        description: "Represents an arbitrary object.",
        parseValue: toObject,
        serialize: toObject,
        parseLiteral(ast) {
            switch(ast.kind) {
                case Kind.STRING:
                    return ast.value.charAt(0) === '{' ? Json5.parse(ast.value) : null;
                case Kind.OBJECT:
                    return parseObject(ast);
            }
            return null;
        }
    });
    
    function toObject(value) {
        if(typeof value === 'object') {
            return value;
        }
        if(typeof value === 'string' && value.charAt(0) === '{') {
            return Json5.parse(value);
        }
        return null;
    }
    
    function parseObject(ast) {
        const value = Object.create(null);
        ast.fields.forEach((field) => {
            value[field.name.value] = parseAst(field.value);
        });
        return value;
    }
    
    function parseAst(ast) {
        switch (ast.kind) {
            case Kind.STRING:
            case Kind.BOOLEAN:
                return ast.value;
            case Kind.INT:
            case Kind.FLOAT:
                return parseFloat(ast.value);
            case Kind.OBJECT: 
                return parseObject(ast);
            case Kind.LIST:
                return ast.values.map(parseAst);
            default:
                return null;
        }
    }
    

相关问题