GraphQL Blackbox /“任何”类型?

问题描述:

是否可以指定GraphQL中的某个字段应该是黑匣子,类似于Flow的“any”类型?我在我的模式中有一个字段,应该能够接受任意值,可以是字符串,布尔值,对象,数组等。GraphQL Blackbox /“任何”类型?

是的。只需创建一个允许任何东西的新的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; 
    } 
} 

我想出了一个中间的解决方案。我没有试图将这种复杂性推到GraphQL上,而是在将其设置在现场之前,只使用String类型和JSON.stringify数据。所以一切都被字符串化,后来在我的应用程序时,我需要消费这一领域,我JSON.parse结果取回所需的对象/数组/布尔/等

@ 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! 
}