问题 GraphQl中的动态(唯一)对象


我在看graphql。是否可以定义具有任意属性的对象?假设我有一些数据:

editOptions : { boxes : 3 , size : { width: 23,height:32} , color: #434343 }, etc...}

这是在:

{ ... , box : { editOptions : {...} }, ... }

假设editOptions从不具有相同的结构,有时对于获得颜色没有用处,例如sakes。在mongoose中,可以将类型定义为:

editOptions:{}

这些editOptions通常对每个框都是唯一的。有些属性是共享的,但大多数都是唯一的。

所以我的问题是,有没有办法做到这一点?或者这是一种不好的做法,我应该改变我的模型。

谢谢。


12080
2017-11-20 05:31


起源



答案:


使用 GraphQLScalarType,简单地实现它:

import { GraphQLScalarType } from 'graphql/type';
import { GraphQLError } from 'graphql/error';
import { Kind } from 'graphql/language';

const ObjectType = new GraphQLScalarType({
  name: 'ObjectType',
  serialize: value => value,
  parseValue: value => value,
  parseLiteral: (ast) => {
    if (ast.kind !== Kind.OBJECT) {
      throw new GraphQLError(
        `Query error: Can only parse object but got a: ${ast.kind}`, 
        [ast],
      );
    }
    return ast.value;
  },
});

const ReturnType = new GraphQLObjectType({
  name: 'ReturnType',
  fields: {
    // ...
    editOptions: { type: ObjectType },
    // ...
  },
});

8
2017-12-11 17:52



我正在尝试使用它,但我收到此消息: "message": "Argument \"data\" has invalid value {a: \"A\", b: \"B\"}.\nExpected type \"ObjectType\", found {a: \"A\", b: \"B\"}."。任何想法在哪里是问题? - Jesús Carrera
似乎你现在可以在这里找到一个公共模块 npmjs.com/package/graphql-type-json。 - jiku


答案:


使用 GraphQLScalarType,简单地实现它:

import { GraphQLScalarType } from 'graphql/type';
import { GraphQLError } from 'graphql/error';
import { Kind } from 'graphql/language';

const ObjectType = new GraphQLScalarType({
  name: 'ObjectType',
  serialize: value => value,
  parseValue: value => value,
  parseLiteral: (ast) => {
    if (ast.kind !== Kind.OBJECT) {
      throw new GraphQLError(
        `Query error: Can only parse object but got a: ${ast.kind}`, 
        [ast],
      );
    }
    return ast.value;
  },
});

const ReturnType = new GraphQLObjectType({
  name: 'ReturnType',
  fields: {
    // ...
    editOptions: { type: ObjectType },
    // ...
  },
});

8
2017-12-11 17:52



我正在尝试使用它,但我收到此消息: "message": "Argument \"data\" has invalid value {a: \"A\", b: \"B\"}.\nExpected type \"ObjectType\", found {a: \"A\", b: \"B\"}."。任何想法在哪里是问题? - Jesús Carrera
似乎你现在可以在这里找到一个公共模块 npmjs.com/package/graphql-type-json。 - jiku


你有两个选择。

1.界面

如果 editOptions 可能会因类型而异,但对于该特定类型是一致的,您可以使用 接口 (node.js的例子)。

假设你有两个物体,一个盒子和一个球体。您可以定义两个实现的对象接口:

interface Object
type Box implements Object {
  editOptions: BoxOptions
}
type BoxOptions {
  boxes: Int,
  size: ...,
  color: ...
}
type Sphere implements Object {
  editOptions: SphereOptions
}
type SphereOptions {
  spheres: Int,
  ...
}
type Query {
  objects: [Object]
}

在您的查询中,您将返回一个 Object,以及基于每种类型的请求选项:

query Query {
  objects(filter: "...") {
    ... on Box {
      editOptions {
        boxes
        size
      }
    }
    ... on Sphere {
      editOptions {
        spheres
      }
    }
  }
}

在返回的JSON中,框将具有 boxes 和 size 领域下 editOptions,和球将有 spheres

有时没有颜色有用

如果某些框中没有颜色,则该字段将为空(但仍存在于模式中)。

2. JSON

如果 editOptions 可以真正变量,你可以只将字段定义为String,并通过序列化的JSON发送。您将丢失所有类型验证,但结构对于每个对象可以完全任意。只需确保您的客户了解如何处理它。


5
2017-12-09 18:30



嘿,对不起回复,这是一个很好的解决方案确实谢谢你。问题是不会像盒子,球体,立方体等那样。我们必须让它开放无限的可能性=)但这绝对是一种可能性。谢谢! - Diogo Barroso