I tried few variant and had no luck to return a map in GraphQL. So I have the following two objects:
public class Customer {
private String name, age;
// getters & setters
}
public class Person {
private String type;
private Map<String, Customer> customers;
// getters & setters
}
My schema looks like this:
type Customer {
name: String!
age: String!
}
type Person {
type: String!
customers: [Customer!] // Here I tried all combination but had no luck, is there a Map type support for GQL?
}
Can someone please tell me how to achieve this so that GraphQL magically process this or an alternative approach.
Many thanks!
In other words, if you return an empty object ( {} ), an empty array ( [] ) or some other value, GraphQL will treat this as you returning an object and not a null value!
HashMap get() Method in Java util. HashMap. get() method of HashMap class is used to retrieve or fetch the value mapped by a particular key mentioned in the parameter. It returns NULL when the map contains no such mapping for the key.
GraphQL is a strongly-typed language, and does not provide any kind of map type out of the box. A JSON blob of key-value pairs do not have a strong schema, so you can't have something like this: { key1: val1, key2: val2, key3: val3, ... }
String! means that the field is non-nullable, meaning that the GraphQL service promises to always give you a value when you query this field.
As you yourself noted, there's no map type in GraphQL, mostly because maps are basically untyped data (or data with a dynamic structure) and, as such, do not translate well into the static types that GraphQL expects. Still, you have a few options.
1) You could change the value type so it includes the key, and give up on the map and use a list instead. This is the approach you took in your own answer. I won't go into detail here as you've already exemplified it.
2) As long as the key and value Java types are known (and not e.g. Object
), you can treat a map as list of key-value pairs. You can create a type to represent the pair:
type Person {
type: String!
customers: [CustomerEntry!]
}
type CustomerEntry {
key: String!
value: Customer!
}
On the down side, you now have uglier queries:
{
person {
type
customers {
key
value {
name
}
}
}
}
On the up side, you keep type safety and (mostly) the semantics. It is possible to keep nesting this approach to e.g. represent a Map<String, Map<Long, Customer>>
.
3) If you ever have a completely unknown type, i.e. Object
, the only option is to treat it as a complex scalar. In JavaScript, this approach is known as JSON scalar as it boils down to stuffing an arbitrary JSON structure in and treating it as a scalar. The same approach can be implemented in Java. graphql-java now has a project for extended scalars. Here's their ObjectScalar (aliased as JsonScalar) implementation.
Now, if you want to represent a type such as Map<String, Object>
, you can opt to represent it using the key-value pair approach from above, with only the value type being the JSON scalar, or you can represent the entire map as a JSON scalar.
As a matter of fact, you can decide to represent any map (well, any type really, but that's not useful) as a JSON scalar.
type MapEntry {
key: String!
value: [ObjectScalar!]
}
scalar ObjectScalar
On the upside, you can now keep any dynamic structure's shape exactly. On the downside, since it is a scalar, it is impossible to make sub-selections, and you're stuck fetching it all, without knowing what's inside in advance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With