私のgraphqlサーバーが次のデータをJSONとしてフェッチするとします。ここでperson3
およびperson5
はいくつかのIDです:
"persons": {
"person3": {
"id": "person3",
"name": "Mike"
},
"person5": {
"id": "person5",
"name": "Lisa"
}
}
質問:アポロを使用してスキーマタイプ定義を作成する方法
キーperson3
およびperson5
ここでは、私のクエリに応じて動的に生成されます(つまり、クエリで使用されるarea
)。したがって、別の機会にperson1
、person2
、person3
戻ってきた。ご覧のように、persons
はIterableではないため、以下はapolloで実行したgraphql型定義としては機能しません。
type Person {
id: String
name: String
}
type Query {
persons(area: String): [Person]
}
persons
オブジェクトのキーは常に異なる場合があります。
もちろん、1つの解決策は、着信JSONデータを変換してpersons
の配列を使用することですが、そのようにデータを処理する方法はありませんか?
GraphQLは、サーバーとクライアントの両方が、各タイプで使用可能なフィールドを事前に知っていることを前提としています。場合によっては、クライアントはそれらのフィールドを(イントロスペクションを介して)検出できますが、サーバーの場合は常に事前に把握しておく必要があります。したがって、返されたデータに基づいてこれらのフィールドを動的に生成することは、実際には不可能です。
あなたcouldはカスタム JSONスカラー (graphql-type-jsonモジュール)を利用し、それをクエリに返します。
type Query {
persons(area: String): JSON
}
JSONを利用することにより、返されたデータが特定の構造に適合するという要件を回避できるため、適切にフォーマットされたJSONであれば、何でも送信できます。
もちろん、これには重大な欠点があります。たとえば、以前に使用したタイプによって提供されたセーフティネットが失われます(文字通り任意の構造が返される可能性があり、間違ったものを返す場合は、クライアントが試行するまでそれを知ることができません。それを使用すると失敗します)。また、返されたデータ内のフィールドに対してリゾルバーを使用する機能も失います。
しかし...あなたの葬式:)
余談ですが、データをクライアントに送信する前に、データをフラット化して(質問で提案したように)配列にすることを検討します。クライアントコードを記述していて、動的にサイズが設定された顧客のリストを操作している場合、IDでキーを指定したオブジェクトよりも、配列を操作する方がはるかに簡単です。たとえば、Reactを使用していて、顧客ごとにコンポーネントを表示している場合は、そのオブジェクトを配列に変換して、とにかくマッピングします。 APIの設計では、クライアントの使いやすさを、データの追加処理を回避することよりも重視します。
独自のGraphQLScalarType
を記述して、オブジェクトと動的キー、許可するものと許可しないもの、または変換できないものを正確に記述することができます。
https://graphql.org/graphql-js/type/#graphqlscalartype を参照してください
taion/graphql-type-json を見ると、あらゆる種類のコンテンツを許可および変換するスカラーが作成されます。
https://github.com/taion/graphql-type-json/blob/master/src/index.js
スキーマの動的キーで同様の問題があり、次のような解決策になりました:
query lookupPersons {
persons {
personKeys
person3: personValue(key: "person1") {
id
name
}
}
}
戻り値:
{
data: {
persons: {
personKeys: ["person1", "person2", "person3"]
person3: {
id: "person3"
name: "Mike"
}
}
}
}
複雑さをクエリにシフトすることで、応答の形状が簡素化されます。 JSONアプローチと比較した場合の利点は、クライアントからの逆シリアル化が不要なことです。