Apollo/GraphQL field type for object with dynamic keys
Let's say my graphql server wants to fetch the following data as JSON where person3
and person5
are some id's:
"persons": {
"person3": {
"id": "person3",
"name": "Mike"
},
"person5": {
"id": "person5",
"name": "Lisa"
}
}
Question: How to create the schema type definition with apollo?
The keys person3
and person5
here are dynamically generated depending on my query (i.e. the area
used in the query). So at another time I might get person1
, person2
, person3
returned.
As you see persons
is not an Iterable, so the following won't work as a graphql type definition I did with apollo:
type Person {
id: String
name: String
}
type Query {
persons(area: String): [Person]
}
The keys in the persons
object may always be different.
One solution of course would be to transform the incoming JSON data to use an array for persons
, but is there no way to work with the data as such?
graphql apollo apollo-server
add a comment |
Let's say my graphql server wants to fetch the following data as JSON where person3
and person5
are some id's:
"persons": {
"person3": {
"id": "person3",
"name": "Mike"
},
"person5": {
"id": "person5",
"name": "Lisa"
}
}
Question: How to create the schema type definition with apollo?
The keys person3
and person5
here are dynamically generated depending on my query (i.e. the area
used in the query). So at another time I might get person1
, person2
, person3
returned.
As you see persons
is not an Iterable, so the following won't work as a graphql type definition I did with apollo:
type Person {
id: String
name: String
}
type Query {
persons(area: String): [Person]
}
The keys in the persons
object may always be different.
One solution of course would be to transform the incoming JSON data to use an array for persons
, but is there no way to work with the data as such?
graphql apollo apollo-server
Can you clarify what you mean byb
andg
beingdynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?
– Daniel Rearden
Oct 4 '17 at 10:55
@DanielRearden Sob
andg
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id'sa
,b
,c
and for another query for exampleb
andg
as in the question.
– Andru
Oct 4 '17 at 11:05
@DanielRearden I now changedb
toperson3
andg
toperson 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.
– Andru
Oct 4 '17 at 11:11
add a comment |
Let's say my graphql server wants to fetch the following data as JSON where person3
and person5
are some id's:
"persons": {
"person3": {
"id": "person3",
"name": "Mike"
},
"person5": {
"id": "person5",
"name": "Lisa"
}
}
Question: How to create the schema type definition with apollo?
The keys person3
and person5
here are dynamically generated depending on my query (i.e. the area
used in the query). So at another time I might get person1
, person2
, person3
returned.
As you see persons
is not an Iterable, so the following won't work as a graphql type definition I did with apollo:
type Person {
id: String
name: String
}
type Query {
persons(area: String): [Person]
}
The keys in the persons
object may always be different.
One solution of course would be to transform the incoming JSON data to use an array for persons
, but is there no way to work with the data as such?
graphql apollo apollo-server
Let's say my graphql server wants to fetch the following data as JSON where person3
and person5
are some id's:
"persons": {
"person3": {
"id": "person3",
"name": "Mike"
},
"person5": {
"id": "person5",
"name": "Lisa"
}
}
Question: How to create the schema type definition with apollo?
The keys person3
and person5
here are dynamically generated depending on my query (i.e. the area
used in the query). So at another time I might get person1
, person2
, person3
returned.
As you see persons
is not an Iterable, so the following won't work as a graphql type definition I did with apollo:
type Person {
id: String
name: String
}
type Query {
persons(area: String): [Person]
}
The keys in the persons
object may always be different.
One solution of course would be to transform the incoming JSON data to use an array for persons
, but is there no way to work with the data as such?
graphql apollo apollo-server
graphql apollo apollo-server
edited Oct 4 '17 at 11:09
Andru
asked Oct 4 '17 at 10:24
AndruAndru
2,09911532
2,09911532
Can you clarify what you mean byb
andg
beingdynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?
– Daniel Rearden
Oct 4 '17 at 10:55
@DanielRearden Sob
andg
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id'sa
,b
,c
and for another query for exampleb
andg
as in the question.
– Andru
Oct 4 '17 at 11:05
@DanielRearden I now changedb
toperson3
andg
toperson 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.
– Andru
Oct 4 '17 at 11:11
add a comment |
Can you clarify what you mean byb
andg
beingdynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?
– Daniel Rearden
Oct 4 '17 at 10:55
@DanielRearden Sob
andg
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id'sa
,b
,c
and for another query for exampleb
andg
as in the question.
– Andru
Oct 4 '17 at 11:05
@DanielRearden I now changedb
toperson3
andg
toperson 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.
– Andru
Oct 4 '17 at 11:11
Can you clarify what you mean by
b
and g
being dynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?– Daniel Rearden
Oct 4 '17 at 10:55
Can you clarify what you mean by
b
and g
being dynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?– Daniel Rearden
Oct 4 '17 at 10:55
@DanielRearden So
b
and g
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id's a
, b
, c
and for another query for example b
and g
as in the question.– Andru
Oct 4 '17 at 11:05
@DanielRearden So
b
and g
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id's a
, b
, c
and for another query for example b
and g
as in the question.– Andru
Oct 4 '17 at 11:05
@DanielRearden I now changed
b
to person3
and g
to person 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.– Andru
Oct 4 '17 at 11:11
@DanielRearden I now changed
b
to person3
and g
to person 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.– Andru
Oct 4 '17 at 11:11
add a comment |
2 Answers
2
active
oldest
votes
GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.
You could utilize a custom JSON scalar and return that for your query:
type Query {
persons(area: String): JSON
}
By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.
Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.
But... your funeral :)
As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
add a comment |
You can write your own GraphQLScalarType
and precisely describe your object and your dynamic keys, what you allow and what you do not allow or transform.
See https://graphql.org/graphql-js/type/#graphqlscalartype
You can have a look at taion/graphql-type-json where he creates a Scalar that allows and transforms any kind of content:
https://github.com/taion/graphql-type-json/blob/master/src/index.js
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46562561%2fapollo-graphql-field-type-for-object-with-dynamic-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.
You could utilize a custom JSON scalar and return that for your query:
type Query {
persons(area: String): JSON
}
By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.
Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.
But... your funeral :)
As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
add a comment |
GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.
You could utilize a custom JSON scalar and return that for your query:
type Query {
persons(area: String): JSON
}
By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.
Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.
But... your funeral :)
As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
add a comment |
GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.
You could utilize a custom JSON scalar and return that for your query:
type Query {
persons(area: String): JSON
}
By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.
Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.
But... your funeral :)
As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.
GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.
You could utilize a custom JSON scalar and return that for your query:
type Query {
persons(area: String): JSON
}
By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.
Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.
But... your funeral :)
As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.
answered Oct 4 '17 at 11:33
Daniel ReardenDaniel Rearden
13.9k11136
13.9k11136
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
add a comment |
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
Thanks for your comments! I transform the incoming data from the server. FYI: The reason for objects with ids was faster retrieval on client side because it's just a lookup of an id to access a particular person.
– Andru
Oct 4 '17 at 15:54
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
My situation is returning validation errors via a Rails / GraphQL API. I don't know in advance what keys will have errors, hence I'm using a custom JSON scalar.
– Tim Fletcher
Feb 21 '18 at 12:06
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
Actually I changed my approach to use nested arrays which allowed me to consistently return the fields with errors.
– Tim Fletcher
Feb 21 '18 at 12:32
add a comment |
You can write your own GraphQLScalarType
and precisely describe your object and your dynamic keys, what you allow and what you do not allow or transform.
See https://graphql.org/graphql-js/type/#graphqlscalartype
You can have a look at taion/graphql-type-json where he creates a Scalar that allows and transforms any kind of content:
https://github.com/taion/graphql-type-json/blob/master/src/index.js
add a comment |
You can write your own GraphQLScalarType
and precisely describe your object and your dynamic keys, what you allow and what you do not allow or transform.
See https://graphql.org/graphql-js/type/#graphqlscalartype
You can have a look at taion/graphql-type-json where he creates a Scalar that allows and transforms any kind of content:
https://github.com/taion/graphql-type-json/blob/master/src/index.js
add a comment |
You can write your own GraphQLScalarType
and precisely describe your object and your dynamic keys, what you allow and what you do not allow or transform.
See https://graphql.org/graphql-js/type/#graphqlscalartype
You can have a look at taion/graphql-type-json where he creates a Scalar that allows and transforms any kind of content:
https://github.com/taion/graphql-type-json/blob/master/src/index.js
You can write your own GraphQLScalarType
and precisely describe your object and your dynamic keys, what you allow and what you do not allow or transform.
See https://graphql.org/graphql-js/type/#graphqlscalartype
You can have a look at taion/graphql-type-json where he creates a Scalar that allows and transforms any kind of content:
https://github.com/taion/graphql-type-json/blob/master/src/index.js
answered Dec 6 '18 at 14:47
LukasLukas
2,40843152
2,40843152
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46562561%2fapollo-graphql-field-type-for-object-with-dynamic-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can you clarify what you mean by
b
andg
beingdynamically generated depending on my query
? Does the presence of one or the other depend on the fields present in the request?– Daniel Rearden
Oct 4 '17 at 10:55
@DanielRearden So
b
andg
are id's. Perhaps I should make that clearer in the question. The query will contain options to only get a subset of people, so for one query the response will contain people with id'sa
,b
,c
and for another query for exampleb
andg
as in the question.– Andru
Oct 4 '17 at 11:05
@DanielRearden I now changed
b
toperson3
andg
toperson 5
and added some text and a variable to make it clearer. The query will contain options to only get a subset of people as now outlined in the text.– Andru
Oct 4 '17 at 11:11