forked from graphql/graphql-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Section 3 -- Type System.md
2215 lines (1680 loc) · 74 KB
/
Section 3 -- Type System.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Type System
The GraphQL Type system describes the capabilities of a GraphQL service and is
used to determine if a requested operation is valid, to guarantee the type of
response results, and describes the input types of variables to determine if
values provided at request time are valid.
TypeSystemDocument : TypeSystemDefinition+
TypeSystemDefinition :
- SchemaDefinition
- TypeDefinition
- DirectiveDefinition
The GraphQL language includes an
[IDL](https://en.wikipedia.org/wiki/Interface_description_language) used to
describe a GraphQL service's type system. Tools may use this definition language
to provide utilities such as client code generation or service boot-strapping.
GraphQL tools or services which only seek to execute GraphQL requests and not
construct a new GraphQL schema may choose not to allow {TypeSystemDefinition}.
Tools which only seek to produce schema and not execute requests may choose to
only allow {TypeSystemDocument} and not allow {ExecutableDefinition} or
{TypeSystemExtension} but should provide a descriptive error if present.
Note: The type system definition language is used throughout the remainder of
this specification document when illustrating example type systems.
## Type System Extensions
TypeSystemExtensionDocument : TypeSystemDefinitionOrExtension+
TypeSystemDefinitionOrExtension :
- TypeSystemDefinition
- TypeSystemExtension
TypeSystemExtension :
- SchemaExtension
- TypeExtension
Type system extensions are used to represent a GraphQL type system which has
been extended from some original type system. For example, this might be used by
a local service to represent data a GraphQL client only accesses locally, or by
a GraphQL service which is itself an extension of another GraphQL service.
Tools which only seek to produce and extend schema and not execute requests may
choose to only allow {TypeSystemExtensionDocument} and not allow
{ExecutableDefinition} but should provide a descriptive error if present.
## Descriptions
Description : StringValue
Documentation is a first-class feature of GraphQL type systems. To ensure
the documentation of a GraphQL service remains consistent with its capabilities,
descriptions of GraphQL definitions are provided alongside their definitions and
made available via introspection.
To allow GraphQL service designers to easily publish documentation alongside the
capabilities of a GraphQL service, GraphQL descriptions are defined using the
Markdown syntax (as specified by [CommonMark](https://commonmark.org/)). In the
type system definition language, these description strings (often {BlockString})
occur immediately before the definition they describe.
GraphQL schema and all other definitions (e.g. types, fields, arguments, etc.)
which can be described should provide a {Description} unless they are considered
self descriptive.
As an example, this simple GraphQL schema is well described:
```raw graphql example
"""
A simple GraphQL schema which is well described.
"""
schema {
query: Query
}
"""
Root type for all your query operations
"""
type Query {
"""
Translates a string from a given language into a different language.
"""
translate(
"The original language that `text` is provided in."
fromLanguage: Language
"The translated language to be returned."
toLanguage: Language
"The text to be translated."
text: String
): String
}
"""
The set of languages supported by `translate`.
"""
enum Language {
"English"
EN
"French"
FR
"Chinese"
CH
}
```
## Schema
SchemaDefinition : Description? schema Directives[Const]? { RootOperationTypeDefinition+ }
RootOperationTypeDefinition : OperationType : NamedType
A GraphQL service's collective type system capabilities are referred to as that
service's "schema". A schema is defined in terms of the types and directives it
supports as well as the root operation types for each kind of operation:
query, mutation, and subscription; this determines the place in the type system
where those operations begin.
A GraphQL schema must itself be internally valid. This section describes
the rules for this validation process where relevant.
All types within a GraphQL schema must have unique names. No two provided types
may have the same name. No provided type may have a name which conflicts with
any built in types (including Scalar and Introspection types).
All directives within a GraphQL schema must have unique names.
All types and directives defined within a schema must not have a name which
begins with {"__"} (two underscores), as this is used exclusively by GraphQL's
introspection system.
### Root Operation Types
A schema defines the initial root operation type for each kind of operation it
supports: query, mutation, and subscription; this determines the place in the
type system where those operations begin.
The {`query`} root operation type must be provided and must be an Object type.
The {`mutation`} root operation type is optional; if it is not provided, the
service does not support mutations. If it is provided, it must be an
Object type.
Similarly, the {`subscription`} root operation type is also optional; if it is
not provided, the service does not support subscriptions. If it is provided, it
must be an Object type.
The {`query`}, {`mutation`}, and {`subscription`} root types must all be
different types if provided.
The fields on the {`query`} root operation type indicate what fields are
available at the top level of a GraphQL query operation.
For example, this example operation:
```graphql example
query {
myName
}
```
is only valid when the {`query`} root operation type has a field named "myName":
```graphql example
type Query {
myName: String
}
```
Similarly, the following mutation is only valid if the {`mutation`} root
operation type has a field named "setName".
```graphql example
mutation {
setName(name: "Zuck") {
newName
}
}
```
When using the type system definition language, a document must include at most
one {`schema`} definition.
In this example, a GraphQL schema is defined with both query and mutation
root operation types:
```graphql example
schema {
query: MyQueryRootType
mutation: MyMutationRootType
}
type MyQueryRootType {
someField: String
}
type MyMutationRootType {
setSomeField(to: String): String
}
```
**Default Root Operation Type Names**
While any type can be the root operation type for a GraphQL operation, the type
system definition language can omit the schema definition when the {`query`},
{`mutation`}, and {`subscription`} root types are named {"Query"}, {"Mutation"},
and {"Subscription"} respectively.
Likewise, when representing a GraphQL schema using the type system definition
language, a schema definition should be omitted if it only uses the default root
operation type names.
This example describes a valid complete GraphQL schema, despite not explicitly
including a {`schema`} definition. The {"Query"} type is presumed to be the
{`query`} root operation type of the schema.
```graphql example
type Query {
someField: String
}
```
### Schema Extension
SchemaExtension :
- extend schema Directives[Const]? { RootOperationTypeDefinition+ }
- extend schema Directives[Const] [lookahead != `{`]
Schema extensions are used to represent a schema which has been extended from
an original schema. For example, this might be used by a GraphQL service which
adds additional operation types, or additional directives to an existing schema.
Note: Schema extensions without additional operation type definitions must not
be followed by a {`{`} (such as a query shorthand) to avoid parsing ambiguity.
The same limitation applies to the type definitions and extensions below.
**Schema Validation**
Schema extensions have the potential to be invalid if incorrectly defined.
1. The Schema must already be defined.
2. Any non-repeatable directives provided must not already apply to the
original Schema.
### Schema Coordinates
Schema Coordinates are human readable strings that uniquely identify an element defined in a GraphQL Schema.
**Definition**
SchemaCoordinate:
- Name
- Name . Name
- Name . Name ( Name : )
- @ Name
- @ Name ( Name : )
**Semantics**
SchemaCoordinate: Name
1. Let {typeName} be the value of the first {Name}.
2. Return the type in the schema named {typeName}.
SchemaCoordinate: Name . Name
1. Let {typeName} be the value of the first {Name}.
2. Let {type} be the type in the schema named {typeName}.
3. If {type} is an Enum type:
1. Let {enumName} be the value of the second {Name}.
2. Return the enum value of {type} named {enumName}.
4. Otherwise if {type} is an Input Object type:
1. Let {inputFieldName} be the value of the second {Name}.
2. Return the input field of {type} named {inputFieldName}.
5. Otherwise {type} must be an Object or Interface type:
1. Let {fieldName} be the value of the second {Name}.
2. Return the field of {type} named {fieldName}.
SchemaCoordinate: Name . Name ( Name : )
1. Let {typeName} be the value of the first {Name}.
2. Let {type} be the type in the schema named {typeName}.
3. Assert: {type} must be an Object or Interface type.
4. Let {fieldName} be the value of the second {Name}.
5. Let {field} be the field of {type} named {fieldName}.
6. Assert: {field} must exist.
7. Let {argumentName} be the value of the third {Name}.
8. Return the argument of {field} named {argumentName}.
SchemaCoordinate: @ Name
1. Let {directiveName} be the value of the first {Name}.
2. Return the directive in the schema named {directiveName}.
SchemaCoordinate: @ Name ( Name : )
1. Let {directiveName} be the value of the first {Name}.
2. Let {directive} be the directive in the schema named {directiveName}.
3. Assert: {directive} must exist.
7. Let {argumentName} be the value of the second {Name}.
8. Return the argument of {directive} named {argumentName}
**Examples**
This section shows example coordinates for the possible schema element types this syntax covers.
All examples below will assume the following schema:
```graphql example
directive @private(scope: String!) on FIELD
scalar DateTime
input ReviewInput {
content: String
author: String
businessId: String
}
interface Address {
city: String
}
type User implements Address {
name: String
reviewCount: Int
friends: [User]
email: String @private(scope: "loggedIn")
city: String
}
type Business implements Address {
name: String
address: String
rating: Int
city: String
reviews: [Review]
createdAt: DateTime
}
type Review {
content: String
author: User
business: Business
createdAt: DateTime
}
union Entity = User | Business | Review
enum SearchFilter {
OPEN_NOW
DELIVERS_TAKEOUT
VEGETARIAN_MENU
}
type Query {
searchBusiness(name: String!, filter: SearchFilter): Business
}
type Mutation {
addReview(input: ReviewInput!): Review
}
```
The following table demonstrates how to select various kinds of schema members:
| Schema Coordinate | Description |
| ------------------------------ | ------------------------------------------------------------------- |
| `Business` | `Business` type |
| `User` | `User` type |
| `Business.name` | `name` field on the `Business` type |
| `User.name` | `name` field on the `User` type |
| `Query.searchBusiness(name:)` | `name` argument on the `searchBusiness` field on the `Query` type |
| `Query.searchBusiness(filter:)`| `filter` argument on the `searchBusiness` field on the `Query` type |
| `SearchFilter` | `SearchFilter` enum |
| `SearchFilter.OPEN_NOW` | `OPEN_NOW` value of the`SearchFilter` enum |
| `@private` | `@private` directive definition |
| `@private(scope:)` | `scope` argument on the `@private` directive definition |
| `Address` | `Address` interface |
| `Address.city` | `city` field on the `Address` interface |
| `ReviewInput` | `ReviewInput` input object type |
| `ReviewInput.author` | `author` field on the `ReviewInput` input object type |
| `Entity` | `Entity` union definition |
| `DateTime` | Custom `DateTime` scalar type |
| `String` | Built-in `String` scalar type |
Note: You may not select members inside a union definition.
The following counter example is *not* considered a valid Schema Coordinate:
```graphql counter-example
Entity.Business
```
In such cases, you may wish to select the type directly instead (e.g. `Business`).
## Types
TypeDefinition :
- ScalarTypeDefinition
- ObjectTypeDefinition
- InterfaceTypeDefinition
- UnionTypeDefinition
- EnumTypeDefinition
- InputObjectTypeDefinition
The fundamental unit of any GraphQL Schema is the type. There are six kinds
of named type definitions in GraphQL, and two wrapping types.
The most basic type is a `Scalar`. A scalar represents a primitive value, like
a string or an integer. Oftentimes, the possible responses for a scalar field
are enumerable. GraphQL offers an `Enum` type in those cases, where the type
specifies the space of valid responses.
Scalars and Enums form the leaves in response trees; the intermediate levels are
`Object` types, which define a set of fields, where each field is another
type in the system, allowing the definition of arbitrary type hierarchies.
GraphQL supports two abstract types: interfaces and unions.
An `Interface` defines a list of fields; `Object` types and other Interface
types which implement this Interface are guaranteed to implement those fields.
Whenever a field claims it will return an Interface type, it will return a
valid implementing Object type during execution.
A `Union` defines a list of possible types; similar to interfaces, whenever the
type system claims a union will be returned, one of the possible types will be
returned.
Finally, oftentimes it is useful to provide complex structs as inputs to
GraphQL field arguments or variables; the `Input Object` type allows the schema
to define exactly what data is expected.
### Wrapping Types
All of the types so far are assumed to be both nullable and singular: e.g. a
scalar string returns either null or a singular string.
A GraphQL schema may describe that a field represents a list of another type;
the `List` type is provided for this reason, and wraps another type.
Similarly, the `Non-Null` type wraps another type, and denotes that the
resulting value will never be {null} (and that a field error cannot result in a
{null} value).
These two types are referred to as "wrapping types"; non-wrapping types are
referred to as "named types". A wrapping type has an underlying named type,
found by continually unwrapping the type until a named type is found.
### Input and Output Types
Types are used throughout GraphQL to describe both the values accepted as input
to arguments and variables as well as the values output by fields. These two
uses categorize types as *input types* and *output types*. Some kinds of types,
like Scalar and Enum types, can be used as both input types and output types;
other kinds of types can only be used in one or the other. Input Object types can
only be used as input types. Object, Interface, and Union types can only be used
as output types. Lists and Non-Null types may be used as input types or output
types depending on how the wrapped type may be used.
IsInputType(type) :
* If {type} is a List type or Non-Null type:
* Let {unwrappedType} be the unwrapped type of {type}.
* Return IsInputType({unwrappedType})
* If {type} is a Scalar, Enum, or Input Object type:
* Return {true}
* Return {false}
IsOutputType(type) :
* If {type} is a List type or Non-Null type:
* Let {unwrappedType} be the unwrapped type of {type}.
* Return IsOutputType({unwrappedType})
* If {type} is a Scalar, Object, Interface, Union, or Enum type:
* Return {true}
* Return {false}
### Type Extensions
TypeExtension :
- ScalarTypeExtension
- ObjectTypeExtension
- InterfaceTypeExtension
- UnionTypeExtension
- EnumTypeExtension
- InputObjectTypeExtension
Type extensions are used to represent a GraphQL type which has been extended
from some original type. For example, this might be used by a local service to
represent additional fields a GraphQL client only accesses locally.
## Scalars
ScalarTypeDefinition : Description? scalar Name Directives[Const]?
Scalar types represent primitive leaf values in a GraphQL type system. GraphQL
responses take the form of a hierarchical tree; the leaves of this tree are
typically GraphQL Scalar types (but may also be Enum types or {null} values).
GraphQL provides a number of built-in scalars which are fully defined in the
sections below, however type systems may also add additional custom scalars to
introduce additional semantic meaning.
**Built-in Scalars**
GraphQL specifies a basic set of well-defined Scalar types: {Int}, {Float},
{String}, {Boolean}, and {ID}. A GraphQL framework should support all of these
types, and a GraphQL service which provides a type by these names must adhere to
the behavior described for them in this document. As an example, a service must
not include a type called {Int} and use it to represent 64-bit numbers,
internationalization information, or anything other than what is defined in
this document.
When returning the set of types from the `__Schema` introspection type, all
referenced built-in scalars must be included. If a built-in scalar type is not
referenced anywhere in a schema (there is no field, argument, or input field of
that type) then it must not be included.
When representing a GraphQL schema using the type system definition language,
all built-in scalars must be omitted for brevity.
**Custom Scalars**
GraphQL services may use custom scalar types in addition to the built-in
scalars. For example, a GraphQL service could define a scalar called `UUID`
which, while serialized as a string, conforms to [RFC 4122](https://tools.ietf.org/html/rfc4122).
When querying a field of type `UUID`, you can then rely on the ability to parse
the result with a RFC 4122 compliant parser. Another example of a potentially
useful custom scalar is `URL`, which serializes as a string, but is guaranteed
by the server to be a valid URL.
When defining a custom scalar, GraphQL services should provide a specification
URL via the `@specifiedBy` directive or the `specifiedBy` introspection field.
This URL must link to a human-readable specification of the data format,
serialization, and coercion rules for the scalar. For example, a GraphQL service
providing a `UUID` scalar may link to RFC 4122, or some custom document defining
a reasonable subset of that RFC. If a scalar `specifiedBy` URL is present,
systems and tools that are aware of it should conform to its described rules.
```graphql example
scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
```
Custom scalar specifications should provide a single, stable format to avoid
ambiguity. If the linked specification is in flux, the service should link to a
fixed version rather than to a resource which might change.
Custom scalar specification URLs should not be changed once defined. Doing so
would likely disrupt tooling or could introduce breaking changes within the
linked specification's contents.
Built-in scalar types must not provide a `specifiedBy` URL as they are specified
by this document.
Note: Custom scalars should also summarize the specified format and provide
examples in their description.
**Result Coercion and Serialization**
A GraphQL service, when preparing a field of a given scalar type, must uphold the
contract the scalar type describes, either by coercing the value or producing a
[field error](#sec-Errors.Field-errors) if a value cannot be coerced or if
coercion may result in data loss.
A GraphQL service may decide to allow coercing different internal types to the
expected return type. For example when coercing a field of type {Int} a boolean
{true} value may produce {1} or a string value {"123"} may be parsed as base-10
{123}. However if internal type coercion cannot be reasonably performed without
losing information, then it must raise a field error.
Since this coercion behavior is not observable to clients of the GraphQL service,
the precise rules of coercion are left to the implementation. The only
requirement is that the service must yield values which adhere to the expected
Scalar type.
GraphQL scalars are serialized according to the serialization format being used.
There may be a most appropriate serialized primitive for each given scalar type,
and the service should produce each primitive where appropriate.
See [Serialization Format](#sec-Serialization-Format) for more detailed
information on the serialization of scalars in common JSON and other formats.
**Input Coercion**
If a GraphQL service expects a scalar type as input to an argument, coercion
is observable and the rules must be well defined. If an input value does not
match a coercion rule, a [request error](#sec-Errors.Request-errors) must be
raised (input values are validated before execution begins).
GraphQL has different constant literals to represent integer and floating-point
input values, and coercion rules may apply differently depending on which type
of input value is encountered. GraphQL may be parameterized by variables, the
values of which are often serialized when sent over a transport like HTTP. Since
some common serializations (ex. JSON) do not discriminate between integer
and floating-point values, they are interpreted as an integer input value if
they have an empty fractional part (ex. `1.0`) and otherwise as floating-point
input value.
For all types below, with the exception of Non-Null, if the explicit value
{null} is provided, then the result of input coercion is {null}.
### Int
The Int scalar type represents a signed 32-bit numeric non-fractional value.
Response formats that support a 32-bit integer or a number type should use
that type to represent this scalar.
**Result Coercion**
Fields returning the type {Int} expect to encounter 32-bit integer
internal values.
GraphQL services may coerce non-integer internal values to integers when
reasonable without losing information, otherwise they must raise a field error.
Examples of this may include returning `1` for the floating-point number `1.0`,
or returning `123` for the string `"123"`. In scenarios where coercion may lose
data, raising a field error is more appropriate. For example, a floating-point
number `1.2` should raise a field error instead of being truncated to `1`.
If the integer internal value represents a value less than -2<sup>31</sup> or
greater than or equal to 2<sup>31</sup>, a field error should be raised.
**Input Coercion**
When expected as an input type, only integer input values are accepted. All
other input values, including strings with numeric content, must raise a request
error indicating an incorrect type. If the integer input value represents a
value less than -2<sup>31</sup> or greater than or equal to 2<sup>31</sup>, a
request error should be raised.
Note: Numeric integer values larger than 32-bit should either use String or a
custom-defined Scalar type, as not all platforms and transports support
encoding integer numbers larger than 32-bit.
### Float
The Float scalar type represents signed double-precision finite values as
specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
Response formats that support an appropriate double-precision number type should
use that type to represent this scalar.
**Result Coercion**
Fields returning the type {Float} expect to encounter double-precision
floating-point internal values.
GraphQL services may coerce non-floating-point internal values to {Float} when
reasonable without losing information, otherwise they must raise a field error.
Examples of this may include returning `1.0` for the integer number `1`, or
`123.0` for the string `"123"`.
Non-finite floating-point internal values ({NaN} and {Infinity}) cannot be
coerced to {Float} and must raise a field error.
**Input Coercion**
When expected as an input type, both integer and float input values are
accepted. Integer input values are coerced to Float by adding an empty
fractional part, for example `1.0` for the integer input value `1`. All
other input values, including strings with numeric content, must raise a request
error indicating an incorrect type. If the input value otherwise represents a
value not representable by finite IEEE 754 (e.g. {NaN}, {Infinity}, or a value
outside the available precision), a request error must be raised.
### String
The String scalar type represents textual data, represented as UTF-8 character
sequences. The String type is most often used by GraphQL to represent free-form
human-readable text. All response formats must support string representations,
and that representation must be used here.
**Result Coercion**
Fields returning the type {String} expect to encounter UTF-8 string internal values.
GraphQL services may coerce non-string raw values to {String} when reasonable
without losing information, otherwise they must raise a field error. Examples of
this may include returning the string `"true"` for a boolean true value, or the
string `"1"` for the integer `1`.
**Input Coercion**
When expected as an input type, only valid UTF-8 string input values are
accepted. All other input values must raise a request error indicating an
incorrect type.
### Boolean
The Boolean scalar type represents `true` or `false`. Response formats should
use a built-in boolean type if supported; otherwise, they should use their
representation of the integers `1` and `0`.
**Result Coercion**
Fields returning the type {Boolean} expect to encounter boolean internal values.
GraphQL services may coerce non-boolean raw values to {Boolean} when reasonable
without losing information, otherwise they must raise a field error. Examples of
this may include returning `true` for non-zero numbers.
**Input Coercion**
When expected as an input type, only boolean input values are accepted. All
other input values must raise a request error indicating an incorrect type.
### ID
The ID scalar type represents a unique identifier, often used to refetch an
object or as the key for a cache. The ID type is serialized in the same way as
a {String}; however, it is not intended to be human-readable. While it is
often numeric, it should always serialize as a {String}.
**Result Coercion**
GraphQL is agnostic to ID format, and serializes to string to ensure consistency
across many formats ID could represent, from small auto-increment numbers, to
large 128-bit random numbers, to base64 encoded values, or string values of a
format like [GUID](https://en.wikipedia.org/wiki/Globally_unique_identifier).
GraphQL services should coerce as appropriate given the ID formats they expect.
When coercion is not possible they must raise a field error.
**Input Coercion**
When expected as an input type, any string (such as `"4"`) or integer (such as
`4` or `-4`) input value should be coerced to ID as appropriate for the ID
formats a given GraphQL service expects. Any other input value, including float
input values (such as `4.0`), must raise a request error indicating an incorrect
type.
### Scalar Extensions
ScalarTypeExtension :
- extend scalar Name Directives[Const]
Scalar type extensions are used to represent a scalar type which has been
extended from some original scalar type. For example, this might be used by a
GraphQL tool or service which adds directives to an existing scalar.
**Type Validation**
Scalar type extensions have the potential to be invalid if incorrectly defined.
1. The named type must already be defined and must be a Scalar type.
2. Any non-repeatable directives provided must not already apply to the
original Scalar type.
## Objects
ObjectTypeDefinition :
- Description? type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
- Description? type Name ImplementsInterfaces? Directives[Const]? [lookahead != `{`]
ImplementsInterfaces :
- ImplementsInterfaces & NamedType
- implements `&`? NamedType
FieldsDefinition : { FieldDefinition+ }
FieldDefinition : Description? Name ArgumentsDefinition? : Type Directives[Const]?
GraphQL operations are hierarchical and composed, describing a tree of
information. While Scalar types describe the leaf values of these hierarchical
operations, 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
selected 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 selection set.
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 type `Person` could be described as:
```graphql example
type Person {
name: String
age: Int
picture: Url
}
```
Where `name` is a field that will yield a {String} value, and `age` is a field
that will yield an {Int} value, and `picture` is a field that will yield a
`Url` 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 of `Person`:
```graphql example
{
name
age
picture
}
```
Would yield the object:
```json example
{
"name": "Mark Zuckerberg",
"age": 30,
"picture": "http://some.cdn/picture.jpg"
}
```
While selecting a subset of fields:
```graphql example
{
age
name
}
```
Must only yield exactly that subset:
```json example
{
"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, the `Person` type might include a `relationship`:
```graphql example
type Person {
name: String
age: Int
picture: Url
relationship: Person
}
```
Valid operations must supply a nested field set for any field that returns an
object, so this operation is not valid:
```graphql counter-example
{
name
relationship
}
```
However, this example is valid:
```graphql example
{
name
relationship {
name
}
}
```
And will yield the subset of each object type queried:
```json example
{
"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 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 the {CollectFields()} algorithm.
Response serialization formats capable of representing ordered maps should
maintain this ordering. Serialization formats which can only represent unordered
maps (such as JSON) should retain this order textually. That is, if two fields
`{foo, bar}` were queried in that order, the resulting JSON serialization
should contain `{"foo": "...", "bar": "..."}` in the same order.
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.
```graphql example
{
foo
...Frag
qux
}
fragment Frag on Query {
bar
baz
}
```
Produces the ordered result:
```json example
{
"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.
```graphql example
{
foo
...Ignored
...Matching
bar
}
fragment Ignored on UnknownType {
qux
baz
}
fragment Matching on Query {
bar
qux
foo
}
```
Produces the ordered result:
```json example
{
"foo": 1,
"bar": 2,
"qux": 3
}
```
Also, if directives result in fields being excluded, they are not considered in
the ordering of fields.
```graphql example
{
foo @skip(if: true)
bar
foo
}
```
Produces the ordered result:
```json example
{
"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.