diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 9ac1b049e..6c927b27a 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -335,13 +335,7 @@ response format being used, there may be a more appropriate primitive for the given scalar type, and server should use those types when appropriate. GraphQL provides a number of built-in scalars, but type systems can add -additional scalars with semantic meaning. For example, a GraphQL system could -define a scalar called `Time` which, while serialized as a string, promises to -conform to ISO-8601. When querying a field of type `Time`, you can then rely on -the ability to parse the result with an ISO-8601 parser and use a -client-specific primitive for time. 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. +additional custom scalars with specific semantic meaning. ```graphql example scalar Time @@ -397,8 +391,8 @@ For all types below, with the exception of Non-Null, if the explicit value **Built-in Scalars** GraphQL provides a basic set of well-defined Scalar types. A GraphQL server -should support all of these types, and a GraphQL server which provide a type by -these names must adhere to the behavior described below. +should support all of these types, and a GraphQL server which provides a type by +these names must adhere to the behavior described for that type. ### Int @@ -531,6 +525,63 @@ input values (such as `4.0`), must raise a query error indicating an incorrect type. +### Custom Scalars + +In addition to GraphQL's built-in scalars, a type system may add additional +custom scalars which provide specific semantic meaning. + +For example, a type system might define a scalar called `Time` which, while +serialized as `String`, promises to conform to ISO-8601. When querying a field +of type `Time`, you can then rely on the ability to parse the result with an +ISO-8601 parser and use a client-specific primitive for time. + +Another example of a potentially useful custom scalar is `Url`, which serializes +as `String`, but is guaranteed by the server to be a valid URL. + +**Serialize as type** + +A custom scalar may provide a built-in scalar type which describes how the +custom scalar is serialized. This provides more information for how execution +responses are query variable inputs are coerced. If provided, this built-in +scalar can be used both for improved validation results and stricter guarantees +during execution. + +While a custom scalar type is not required to provide a serialize as type, if +one is provided it must be one of the built-in scalar types (`Int`, `Float`, +`String`, `Boolean`, `ID`). + +**Result Coercion** + +If a custom scalar provides a built-in scalar type which it serializes as, then +that custom scalar must coerce using the same rules as that built-in scalar +type. Using the example above, if a custom scalar `Time` declares it serializes +as a `String`, then the result of a field of type `Time` must produce a +`String`, which may be subject to additional coercion rules specific to the +custom scalar type. + +If a custom scalar does not provide a built-in scalar type which it serializes +as, then since this coercion behavior is not observable to clients of the +GraphQL server, the precise rules of coercion are left to the implementation, +and the serialized form will not be known ahead of time. + +**Input Coercion** + +If a custom scalar provides a built-in scalar type which it serializes as, then +that custom scalar should accept the same kinds of input which that built-in +scalar type accepts and must produce an error for the kinds of input for which +that built-in scalar type would produce an error. Using the example above, if a +custom scalar `Time` declares it serializes as a `String`, then it should accept +`String` values and must not accept `Int` or `Float` values as input. + +A custom scalar may provide additional rules for coercing input values as +implementation details, producing a query error when it deems necessary. + +If a custom scalar does not provide a built-in scalar type which it serializes +as, then since this input coercion behavior is not observable to clients of the +GraphQL server, the precise rules of coercion are left to the implementation, +and the allowed input values will not be known ahead of time. + + ### Scalar Extensions ScalarTypeExtension : diff --git a/spec/Section 4 -- Introspection.md b/spec/Section 4 -- Introspection.md index 8a24e2882..1b6d16a83 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -144,7 +144,7 @@ type __Type { # INPUT_OBJECT only inputFields: [__InputValue!] - # NON_NULL and LIST only + # SCALAR, NON_NULL, and LIST only ofType: __Type } @@ -232,7 +232,10 @@ actually valid. These kinds are listed in the `__TypeKind` enumeration. Represents scalar types such as Int, String, and Boolean. Scalars cannot have fields. -A GraphQL type designer should describe the data format and scalar coercion +Custom scalars may provide a built-in scalar type it serializes as in `ofType`, +which describe primary data format and scalar coercion rules. + +A GraphQL type designer should describe further data format and scalar coercion rules in the description field of any scalar. Fields @@ -240,6 +243,7 @@ Fields * `kind` must return `__TypeKind.SCALAR`. * `name` must return a String. * `description` may return a String or {null}. +* `ofType`: one of the built-in scalar types or {null}. * All other fields must return {null}.