2017-08-09 82 views
4

是否可以指定GraphQL中的某個字段應該是黑匣子,類似於Flow的「any」類型?我在我的模式中有一個字段,應該能夠接受任意值,可以是字符串,布爾值,對象,數組等。GraphQL Blackbox /「任何」類型?

回答

3

是的。只需創建一個允許任何東西的新的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; 
    } 
} 
3

我想出了一箇中間的解決方案。我沒有試圖將這種複雜性推到GraphQL上,而是在將其設置在現場之前,只使用String類型和JSON.stringify數據。所以一切都被字符串化,後來在我的應用程序時,我需要消費這一領域,我JSON.parse結果取回所需的對象/數組/布爾/等

0

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