2017-01-09 10 views
1

Я искал GraphQL в качестве замены некоторых API-интерфейсов REST, и, хотя я думаю, что я обернул голову вокруг основ и, как и большинство из того, что я вижу до сих пор, одна важная функция, которая, кажется, отсутствует.Пользовательские ключи карты в ответе GraphQL

Скажем, у меня есть коллекция предметов, как это:

{ 
    "id": "aaa", 
    "name": "Item 1", 
    ... 
} 

Приложение нужна карта всех этих объектов, индексируются ID, как например:

{ 
    "allItems": { 
     "aaa": { 
      "name": "Item 1", 
      ... 
     }, 
     "aab": { 
      "name": "Item 2", 
      ... 
     } 
    } 
} 

Каждый API I «когда-либо написанный, смог вернуть результаты в таком формате, но я изо всех сил пытаюсь найти способ сделать это с помощью GraphQL. Я продолжаю работать через issue 101, но это больше связано с неизвестными схемами. В моем случае я точно знаю, что такое все поля; это чисто формат вывода. Я знаю, что могу просто вернуть все элементы в массиве и переформатировать его на стороне клиента, но это похоже на излишний прилив, учитывая, что он никогда не был нужен в прошлом и заставил GraphQL чувствовать себя как шаг назад. Я не уверен, что то, что я пытаюсь сделать, невозможно, или я просто использую неправильную терминологию. Должен ли я продолжать копать, или GraphQL просто не подходит для моих нужд? Если это возможно, что может выглядеть запрос для получения таких данных?

В настоящее время я работаю с graphql-php на сервере, но я открыт для более концептуальных ответов более высокого уровня.

+0

«и заставит GraphQL чувствовать себя как шаг назад» - в вашем случае, возможно, вы знаете, что потребуется каждому клиенту веб-службы. В противном случае вы делаете предположение, что карта - это то, что нужно клиенту. Клиентам, которым требуется обратное тому, что возвращает веб-служба, необходимо сделать какое-то преобразование. ИМХО, решение о том, следует ли возвращать карту или коллекцию в стиле массива, - это стирка, так как это 50:50, хочет ли клиент тот или иной. – CommonsWare

+0

@CommonsWare API, который я имею в виду, на данный момент используется только внутри организации, поэтому да, я могу с уверенностью сказать, что все клиенты нуждаются в данных в том формате, в котором они всегда получали его. Это называется загрузку страницы как быстрый указатель для целей локального поиска, а расширенные детали детали извлекаются (в формате, легко представленном GraphQL) по мере необходимости.Вопрос в том, возможно ли то, что я пытаюсь сделать. –

+0

«всем клиентам нужны эти данные в том формате, в котором они всегда его получали». Преобразование коллекции в карту занимает 1-3 строки кода на большинстве современных языков программирования. «GraphQL просто не подходит для моих нужд?» - если вам требуется, чтобы веб-служба возвращала определенную структуру JSON, тогда GraphQL не подходит. Даже если вы пройдете мимо этого случая (и я не знаю о решении), вы столкнетесь с чем-то другим. У вас нет абсолютного контроля над структурой JSON, которая продиктована схемой, а схема не предназначена для обработки произвольных структур. – CommonsWare

ответ

5

К сожалению, возвращение объектов с произвольными и динамическими ключами, как это, на самом деле не является первоклассным гражданином в GraphQL. Это не значит, что вы не можете достичь того же, но при этом вы потеряете много преимуществ GraphQL.

Если вы хотите вернуть объект с ключами id вместо того, чтобы возвращать коллекцию/список объектов, содержащих идентификаторы, а затем делать преобразование на клиенте, то вы можете создать специальный GraphQLScalarType.

const GraphQLAnyObject = new GraphQLScalarType({ 
    name: 'AnyObject', 
    description: 'Any JSON object. This type bypasses type checking.', 
    serialize: value => { 
    return value; 
    }, 
    parseValue: value => { 
    return 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; 
    } 
}); 

Проблема такого подхода заключается в том, что, поскольку он является скалярный тип, вы не можете поставить выбор набора для запроса его. НАПРИМЕР. если у вас тип

type MyType implements Node { 
    id: ID! 
    myKeyedCollection: AnyObject 
} 

Тогда вы бы только иметь возможность запросить его, как так

query { 
    getMyType(id: abc) { 
    myKeyedCollection # note there is no { ... } 
    } 
} 

Как уже сказал, я не рекомендовал бы это, потому что вы теряете много преимуществ GraphQL, но он показывает, что GraphQL все еще может делать что угодно, что может сделать REST. Если вы просто хотите попробовать, мы предоставляем типы AnyObject на scaphold.io, с которыми вы можете играть.

Надеюсь, это поможет!