Objects
GraphQL queries are hierarchical and composed, describing a tree of information. While Scalar types describe the leaf values of these hierarchical queries, Objects describe the intermediate levels.
GraphQL Objects represent a list of named fields, each of which yield a value of a specific type. Object values should be serialized as ordered maps, where the queried field names (or aliases) are the keys and the result of evaluating the field is the value, ordered by the order in which they appear in the query.
All fields defined within an Object type must not have a name which begins with"__"(two underscores), as this is used exclusively by GraphQL’s introspection system.
For example, a typePerson
could be described as:
type Person {
name: String
age: Int
picture: Url
}
Wherename
is a field that will yield aString
value, andage
is a field that will yield anInt
value, andpicture
is a field that will yield aUrl
value.
A query of an object value must select at least one field. This selection of fields will yield an ordered map containing exactly the subset of the object queried, which should be represented in the order in which they were queried. Only fields that are declared on the object type may validly be queried on that object.
For example, selecting all the fields ofPerson
:
{
name
age
picture
}
Would yield the object:
{
"name": "Mark Zuckerberg",
"age": 30,
"picture": "http://some.cdn/picture.jpg"
}
While selecting a subset of fields:
{
age
name
}
Must only yield exactly that subset:
{
"age": 30,
"name": "Mark Zuckerberg"
}
A field of an Object type may be a Scalar, Enum, another Object type, an Interface, or a Union. Additionally, it may be any wrapping type whose underlying base type is one of those five.
For example, thePerson
type might include arelationship
:
type Person {
name: String
age: Int
picture: Url
relationship: Person
}
Valid queries must supply a nested field set for a field that returns an object, so this query is not valid:
{
name
relationship
}
However, this example is valid:
{
name
relationship {
name
}
}
And will yield the subset of each object type queried:
{
"name": "Mark Zuckerberg",
"relationship": {
"name": "Priscilla Chan"
}
}
Field Ordering
When querying an Object, the resulting mapping of fields are conceptually ordered in the same order in which they were encountered during query execution, excluding fragments for which the type does not apply and fields or fragments that are skipped via@skip
or@include
directives. This ordering is correctly produced when using theCollectFields()algorithm.
Response serialization formats capable of representing ordered maps should maintain this ordering. Serialization formats which can only represent unordered maps should retain this order grammatically (such as JSON).
Producing a response where fields are represented in the same order in which they appear in the request improves human readability during debugging and enables more efficient parsing of responses if the order of properties can be anticipated.
If a fragment is spread before other fields, the fields that fragment specifies occur in the response before the following fields.
{
foo
...Frag
qux
}
fragment Frag on Query {
bar
baz
}
Produces the ordered result:
{
"foo": 1,
"bar": 2,
"baz": 3,
"qux": 4
}
If a field is queried multiple times in a selection, it is ordered by the first time it is encountered. However fragments for which the type does not apply does not affect ordering.
{
foo
...Ignored
...Matching
bar
}
fragment Ignored on UnknownType {
qux
baz
}
fragment Matching on Query {
bar
qux
foo
}
Produces the ordered result:
{
"foo": 1,
"bar": 2,
"qux": 3
}
Also, if directives result in fields being excluded, they are not considered in the ordering of fields.
{
foo @skip(if: true)
bar
foo
}
Produces the ordered result:
{
"bar": 1,
"foo": 2
}
Result Coercion
Determining the result of coercing an object is the heart of the GraphQL executor, so this is covered in that section of the spec.
Input Coercion
Objects are never valid inputs.