I’m currently working on a GraphQL/Node/Express server that retrieves data from another API. I have absolutely no access to the other API except for the data I receive back.
My problem is that the response is XML and there are certain fields that should be returned as arrays but instead are being returned as objects (or dictionaries) if the array has only one item in it.
This blog post explains the issue in more detail.
Is there a way in GraphQL to design the schema in such a way that if it receives an object for a property that is defined as an array, that it places the object into an array?
Examples
Current behaviour
<team>
<employee>
<name>Joe</name>
<surname>Bloggs</surname>
</employee>
<employee>
<name>Jane</name>
<surname>Doe</surname>
</employee>
</team>
The above XML will convert to JSON as below
{
team:{
employee:[
{
name:'Joe',
surname:'Bloggs'
},
{
name:'Jane',
surname:'Doe'
}
]
}
}
But if there is only one employee
<team>
<employee>
<name>Joe</name>
<surname>Bloggs</surname>
</employee>
</team>
The above XML will convert to JSON as below, where employee
becomes an object rather than an array
{
team:{
employee:{
name:'Joe',
surname:'Bloggs'
}
}
}
2 Answers
Yes, it’s possible and easy to implement
With Apollo you define resolver maps that will be used to resolve all the fields and sub fields of your types, for queries and mutations.
In your case, you could write a resolver for the specific field employee
on the Team
type, that will make sure to return an array.
{
Team: {
employee(parentObject, args, context) {
const {employee} = parentObject
// you should probably handle the case when employee is null or undefined
return Array.isArray(employee) ? employee : [employee]
}
...
}
The result will be:
{
team: {
employee: [
{
name:'Joe',
surname:'Bloggs'
}
]
}
}
Note: you don’t have to implement all the resolver functions by yourself. If you did not provide a resolver function for a field, Apollo will use a default resolver. That usually means simply returning the value as it is.