Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Scalar serialize as built-in scalar type #521

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 60 additions & 9 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 :
Expand Down
8 changes: 6 additions & 2 deletions spec/Section 4 -- Introspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ type __Type {
# INPUT_OBJECT only
inputFields: [__InputValue!]

# NON_NULL and LIST only
# SCALAR, NON_NULL, and LIST only
ofType: __Type
}

Expand Down Expand Up @@ -232,14 +232,18 @@ 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

* `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}.


Expand Down