Динамические (уникальные) объекты в GraphQl
Я смотрю на graphql. Можно ли определить объект с произвольными атрибутами? Скажем, у меня есть некоторые данные вроде:
editOptions : { boxes : 3 , size : { width: 23,height:32} , color: #434343 }, etc...}
и это находится в:
{ ... , box : { editOptions : {...} }, ... }
Скажем, что editOptions никогда не имеет одинаковую структуру, иногда не полезно использовать цвет, например, например. В мангусте можно просто указать тип на что-то вроде:
editOptions: {}
Эти editOptions обычно уникальны для каждого окна. С некоторыми атрибутами, которые разделяются, но большинство из них уникальны.
Итак, мой вопрос: есть ли способ сделать это? или это плохая практика, и я должен изменить свои модели.
Спасибо.
Ответы
Ответ 1
Используйте 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 },
// ...
},
});
Ответ 2
У вас есть два варианта.
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. Вы потеряете все проверки типов, но структура может быть абсолютно произвольной для каждого объекта. Просто убедитесь, что ваш клиент понимает, что с ним делать.
Ответ 3
Попробуйте скалярный тип JSON для GraphQL.js: graphql-type-json. Это отлично работает для меня.
При использовании SDL с инструментами GraphQL определите GraphQLJSON в качестве преобразователя для соответствующего типа скаляра в вашей схеме:
import { makeExecutableSchema } from 'graphql-tools';
import GraphQLJSON from 'graphql-type-json';
const typeDefs = '
scalar JSON
type MyType {
editOptions: JSON
}
';
const resolvers = {
JSON: GraphQLJSON,
};
export default makeExecutableSchema({ typeDefs, resolvers });
Вы также можете использовать это в программно построенной схеме.
Подробнее об этом пакете см.