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