学习教程
结构和类型

结构和类型

¥Schemas and Types

Learn about the different elements of the GraphQL type system

GraphQL 类型系统 描述了可以从 API 查询哪些数据。这些功能的集合称为服务的模式,客户端可以使用该模式向 API 发送返回可预测结果的查询。

¥The GraphQL type system describes what data can be queried from the API. The collection of those capabilities is referred to as the service’s schema and clients can use that schema to send queries to the API that return predictable results.

在此页面上,我们将探索 GraphQL 的 六种命名类型定义 以及类型系统的其他功能,以了解如何使用它们来描述你的数据及其之间的关系。由于 GraphQL 可以与任何后端框架或编程语言一起使用,我们将避免特定于实现的细节,只讨论概念。

¥On this page, we’ll explore GraphQL’s six kinds of named type definitions as well as other features of the type system to learn how they may be used to describe your data and the relationships between them. Since GraphQL can be used with any backend framework or programming language, we’ll avoid implementation-specific details and talk only about the concepts.

类型系统

¥Type system

如果你以前见过 GraphQL 查询,你就会知道 GraphQL 查询语言基本上是关于选择对象上的字段。因此,例如,在以下查询中:

¥If you’ve seen a GraphQL query before, you know that the GraphQL query language is basically about selecting fields on objects. So, for example, in the following query:

Operation
Response
  1. 我们从一个特殊的 “root” 对象开始

    ¥We start with a special “root” object

  2. 我们选择 hero 字段

    ¥We select the hero field on that

  3. 对于 hero 返回的对象,我们选择 nameappearsIn 字段

    ¥For the object returned by hero, we select the name and appearsIn fields

由于 GraphQL 查询的形状与结果非常匹配,因此我们可以预测查询将返回什么,而无需了解太多有关服务器的信息。但对我们可以请求的数据有一个准确的描述是很有用的。例如,我们可以选择哪些字段?他们可能返回什么类型的对象?这些子对象有哪些可用字段?

¥Because the shape of a GraphQL query closely matches the result, we can predict what the query will return without knowing that much about the server. But it’s useful to have an exact description of the data we can request. For example, what fields can we select? What kinds of objects might they return? What fields are available on those sub-objects?

这就是结构的用武之地。每个 GraphQL 服务都定义了一组类型,这些类型完全描述了我们可以在该服务上查询的可能数据集。然后,当请求进入时,将根据该模式对其进行验证和执行。

¥That’s where the schema comes in. Every GraphQL service defines a set of types that completely describe the set of possible data we can query on that service. Then, when requests come in, they are validated and executed against that schema.

类型语言

¥Type language

GraphQL 服务可以用任何语言编写,在模式中定义类型时,你可以采用多种不同的方法:

¥GraphQL services can be written in any language and there are many different approaches you can take when defining the types in a schema:

  • 有些库让你使用与编写 GraphQL 实现相同的编程语言一起构建模式类型、字段和解析器函数。

    ¥Some libraries have you construct the schema types, fields, and resolver functions together using the same programming language that was used to write the GraphQL implementation.

  • 有些库允许你使用通常称为模式定义语言(或 SDL)的语言更符合人机工程学地定义类型和字段,然后分别为相应字段编写解析器函数。

    ¥Some libraries allow you to define types and fields more ergonomically using what’s commonly called the schema definition language (or SDL) and then write the resolver functions for the corresponding fields separately.

  • 有些库允许你编写和注释解析器函数,然后从中推断模式。

    ¥Some libraries allow you to write and annotate the resolver functions, and then infer the schema from that.

  • 有些库甚至可能根据一些底层数据源为你推断类型和解析器函数。

    ¥Some libraries may even infer both the types and resolver functions for you, based on some underlying data source(s).

由于我们不能依赖特定的编程语言来在本指南中讨论 GraphQL 模式,因此我们将使用 SDL,因为它类似于我们迄今为止看到的查询语言,并允许我们以与语言无关的方式讨论 GraphQL 模式。

¥Since we can’t rely on a specific programming language to discuss GraphQL schemas in this guide, we’ll use SDL because it’s similar to the query language that we’ve seen so far and allows us to talk about GraphQL schemas in a language-agnostic way.

对象类型和字段

¥Object types and fields

GraphQL 模式的最基本组件是 对象类型,它仅表示你可以从服务中获取的一种对象,以及它具有哪些字段。在 SDL 中,我们这样表示:

¥The most basic components of a GraphQL schema are Object types, which just represent a kind of object you can fetch from your service, and what fields it has. In SDL, we represent it like this:

type Character {
  name: String!
  appearsIn: [Episode!]!
}

该语言是可读的,但让我们回顾一下,以便我们可以拥有一个共享的词汇表:

¥The language is readable, but let’s go over it so that we can have a shared vocabulary:

  • CharacterGraphQL 对象类型,这意味着它是一种具有一些字段的类型。架构中的大多数类型都是对象类型。

    ¥Character is a GraphQL Object type, meaning it’s a type with some fields. Most of the types in your schema will be Object types.

  • nameappearsInCharacter 类型上的 fields。这意味着 nameappearsIn 是唯一可以出现在对 Character 类型进行操作的 GraphQL 查询的任何部分中的字段。

    ¥name and appearsIn are fields on the Character type. That means that name and appearsIn are the only fields that can appear in any part of a GraphQL query that operates on the Character type.

  • String 是内置 标量类型 之一。这些类型解析为单个标量值,并且在查询中不能有子选择。我们稍后会详细介绍标量类型。

    ¥String is one of the built-in Scalar types. These are types that resolve to a single scalar value and can’t have sub-selections in the query. We’ll go over Scalar types more later.

  • String! 表示该字段是 非空类型,这意味着 GraphQL 服务承诺在你查询此字段时为你提供一个值。在 SDL 中,我们用感叹号表示。

    ¥String! means that the field is a Non-Null type, meaning the GraphQL service promises to give you a value whenever you query this field. In SDL, we represent those with an exclamation mark.

  • [Episode!]! 表示 Episode 对象的 列表类型。当列表非空时,查询 appearsIn 字段时总是可以得到一个数组(包含零个或多个项目)。在这种情况下,由于 Episode! 在列表中也是非空的,因此你始终可以期望数组中的每个项目都是 Episode 对象。

    ¥[Episode!]! represents an List type of Episode objects. When a List is Non-Null, you can always expect an array (with zero or more items) when you query the appearsIn field. In this case, since Episode! is also Non-Null within the list, you can always expect every item in the array to be an Episode object.

现在你知道 GraphQL 对象类型是什么样的以及如何读取 SDL 的基础知识。

¥Now you know what a GraphQL Object type looks like and how to read the basics of SDL.

参数

¥Arguments

GraphQL 对象类型上的每个字段都可以有零个或多个 arguments,例如下面的 length 字段:

¥Every field on a GraphQL Object type can have zero or more arguments, for example, the length field below:

type Starship {
  id: ID!
  name: String!
  length(unit: LengthUnit = METER): Float
}

所有参数均已命名。与 JavaScript 和 Python 等语言不同,在这些语言中函数采用有序参数列表,而 GraphQL 中的所有参数都是通过名称传递的。在这种情况下,length 字段有一个定义的参数,称为 unit

¥All arguments are named. Unlike languages such as JavaScript and Python where functions take a list of ordered arguments, all arguments in GraphQL are passed by name specifically. In this case, the length field has one defined argument called unit.

参数可以是必需的,也可以是可选的。当参数是可选的时,我们可以定义一个默认值。如果未传递 unit 参数,则默认情况下它将设置为 METER

¥Arguments can be either required or optional. When an argument is optional, we can define a default value. If the unit argument is not passed, then it will be set to METER by default.

查询、变异和订阅类型

¥The Query, Mutation, and Subscription types

每个 GraphQL 模式都必须支持 query 操作。此 根操作类型 的入口点是默认情况下称为 Query 的常规对象类型。因此,如果你看到如下所示的查询:

¥Every GraphQL schema must support query operations. The entry point for this root operation type is a regular Object type called Query by default. So if you see a query that looks like this:

Operation
Response

这意味着 GraphQL 服务需要具有带有 droid 字段的 Query 类型:

¥That means that the GraphQL service needs to have a Query type with a droid field:

type Query {
  droid(id: ID!): Droid
}

架构还可以通过添加其他 MutationSubscription 类型然后在相应的根操作类型上定义字段来支持 mutationsubscription 操作。

¥Schemas may also support mutation and subscription operations by adding additional Mutation and Subscription types and then defining fields on the corresponding root operation types.

重要的是要记住,除了作为架构入口点的特殊状态外,QueryMutationSubscription 类型与任何其他 GraphQL 对象类型相同,并且它们的字段的工作方式完全相同。

¥It’s important to remember that other than the special status of being entry points into the schema, the Query, Mutation, and Subscription types are the same as any other GraphQL Object type, and their fields work exactly the same way.

你也可以为根操作类型命名不同的名字;如果你选择这样做,则需要使用 schema 关键字将新名称通知 GraphQL:

¥You can name your root operation types differently too; if you choose to do so then you will need to inform GraphQL of the new names using the schema keyword:

schema {
  query: MyQueryType
  mutation: MyMutationType
  subscription: MySubscriptionType
}

标量类型

¥Scalar types

GraphQL 对象类型具有名称和字段,但在某些时候,这些字段必须解析为一些具体的数据。这就是 标量类型 的用武之地:它们代表查询的叶值。

¥A GraphQL Object type has a name and fields, but at some point, those fields must resolve to some concrete data. That’s where the Scalar types come in: they represent the leaf values of the query.

在以下查询中,nameappearsIn 字段将解析为标量类型:

¥In the following query, the name and appearsIn fields will resolve to Scalar types:

Operation
Response

我们知道这一点,因为这些字段没有任何子字段 - 它们是查询的叶子。

¥We know this because those fields don’t have any sub-fields—they are the leaves of the query.

GraphQL 附带一组开箱即用的 默认标量类型

¥GraphQL comes with a set of default Scalar types out of the box:

  • Int:有符号 32 位整数。

    ¥Int: A signed 32‐bit integer.

  • Float:有符号双精度浮点值。

    ¥Float: A signed double-precision floating-point value.

  • String:UTF-8 字符序列。

    ¥String: A UTF‐8 character sequence.

  • Booleantruefalse

    ¥Boolean: true or false.

  • ID:唯一标识符,通常用于重新获取对象或作为缓存的键。ID 类型的序列化方式与 String 相同;然而,将其定义为 ID 意味着它不适合人类可读。

    ¥ID: 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, defining it as an ID signifies that it is not intended to be human‐readable.

在大多数 GraphQL 服务实现中,还有一种方法可以指定自定义标量类型。例如,我们可以定义一个 Date 类型:

¥In most GraphQL service implementations, there is also a way to specify custom Scalar types. For example, we could define a Date type:

scalar Date

然后由我们的实现来定义如何序列化、反序列化和验证该类型。例如,你可以指定 Date 类型应始终序列化为整数时间戳,并且你的客户端应该知道任何日期字段都应采用该格式。

¥Then it’s up to our implementation to define how that type should be serialized, deserialized, and validated. For example, you could specify that the Date type should always be serialized into an integer timestamp, and your client should know to expect that format for any date fields.

枚举类型

¥Enum types

枚举类型,也称为枚举类型,是一种特殊的标量,仅限于一组特定的允许值。这使你能够:

¥Enum types, also known as enumeration types, are a special kind of scalar that is restricted to a particular set of allowed values. This allows you to:

  1. 验证此类型的任何参数是否都是允许的值之一

    ¥Validate that any arguments of this type are one of the allowed values

  2. 通过类型系统传达字段始终是有限值集之一的信息

    ¥Communicate through the type system that a field will always be one of a finite set of values

以下是 SDL 中枚举类型定义的样子:

¥Here’s what an Enum type definition looks like in SDL:

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

这意味着无论我们在结构中使用类型 Episode,我们都希望它恰好是 NEWHOPEEMPIREJEDI 之一。

¥This means that wherever we use the type Episode in our schema, we expect it to be exactly one of NEWHOPE, EMPIRE, or JEDI.

GraphQL service implementations in various languages will have a language-specific way of dealing with Enum types. In languages that support enums as a first-class citizen, the implementation might take advantage of that; in a language like JavaScript with no enum support, these values might be internally mapped to a set of integers. However, these details don’t leak out to the client, which can operate entirely in terms of the string names of the Enum type’s values.

类型修饰符

¥Type modifiers

在 GraphQL 中,类型默认为可空且单数。但是,当你在架构中(或在 查询变量声明 中)使用这些命名类型时,你可以应用会影响这些值含义的其他类型修饰符。

¥Types are assumed to be nullable and singular by default in GraphQL. However, when you use these named types in a schema (or in query variable declarations) you can apply additional type modifiers that will affect the meaning of those values.

如上例所示,GraphQL 支持两种类型修饰符 - 列表非空 类型 - 它们可以单独使用,也可以相互组合使用。

¥As we saw with the Object type example above, GraphQL supports two type modifiers—the List and Non-Null types—and they can be used individually or in combination with each other.

非空

¥Non-Null

让我们看一个例子:

¥Let’s look at an example:

type Character {
  name: String!
}

这里,我们使用 String 类型,并通过在类型名称后添加感叹号 (!) 将其标记为非空类型。这意味着我们的服务器始终期望为此字段返回一个非空值,如果解析器生成一个空值,那么这将触发 GraphQL 执行错误,让客户端知道出了问题。

¥Here, we’re using a String type and marking it as a Non-Null type by adding an exclamation mark (!) after the type name. This means that our server always expects to return a non-null value for this field, and if the resolver produces a null value, then that will trigger a GraphQL execution error, letting the client know that something has gone wrong.

如上例所示,Non-Null 类型修饰符也可用于定义字段的参数,如果传递了空值作为该参数,GraphQL 服务器将返回验证错误:

¥As we saw in an example above, the Non-Null type modifier can also be used when defining arguments for a field, which will cause the GraphQL server to return a validation error if a null value is passed as that argument:

Operation
Response

列表

¥List

列表以类似的方式工作。我们可以使用类型修饰符将类型标记为 List 类型,这表明该字段将返回该类型的数组。在 SDL 中,这通过将类型括在方括号中来表示,[]。对于参数来说,它的工作方式相同,其中验证步骤将期望该值的数组。这是一个例子:

¥Lists work in a similar way. We can use a type modifier to mark a type as a List type, which indicates that this field will return an array of that type. In SDL, this is denoted by wrapping the type in square brackets, [ and ]. It works the same for arguments, where the validation step will expect an array for that value. Here’s an example:

type Character {
  name: String!
  appearsIn: [Episode]!
}

如上所示,Non-Null 和 List 修饰符可以组合使用。例如,你可以有一个非空 String 类型的列表:

¥As we see above, the Non-Null and List modifiers can be combined. For example, you can have a List of Non-Null String types:

myField: [String!]

这意味着列表本身可以为空,但不能有任何空成员。例如,在 JSON 中:

¥This means that the list itself can be null, but it can’t have any null members. For example, in JSON:

myField: null // valid
myField: [] // valid
myField: ["a", "b"] // valid
myField: ["a", null, "b"] // error

现在,假设我们定义了一个 String 类型的非空列表:

¥Now, let’s say we defined a Non-Null List of String types:

myField: [String]!

这意味着列表本身不能为空,但它可以包含空值:

¥This means that the list itself cannot be null, but it can contain null values:

myField: null // error
myField: [] // valid
myField: ["a", "b"] // valid
myField: ["a", null, "b"] // valid

最后,你还可以拥有一个非空 String 类型的非空列表:

¥Lastly, you can also have a Non-Null List of Non-Null String types:

myField: [String!]!

这意味着列表不能为空,也不能包含空值:

¥This means that the list cannot be null and it cannot contain null values:

myField: null // error
myField: [] // valid
myField: ["a", "b"] // valid
myField: ["a", null, "b"] // error

你可以根据需要任意嵌套任意数量的 Non-Null 和 List 修饰符。

¥You can arbitrarily nest any number of Non-Null and List modifiers, according to your needs.

In GraphQL, there is no way to define a type so that the field’s data will only be considered valid if a non-empty list is provided. In other words, [] would still be a valid response for a Non-Null List of a Non-Null type.

接口类型

¥Interface types

与许多类型系统一样,GraphQL 支持抽象类型。我们将要探索的第一个类型是 接口类型,它定义了一组特定的字段,具体对象类型或其他接口类型也必须包含这些字段才能实现它。

¥Like many type systems, GraphQL supports abstract types. The first of these types that we’ll explore is an Interface type, which defines a certain set of fields that a concrete Object type or other Interface type must also include to implement it.

例如,你可以有一个代表星球大战三部曲中任何角色的 Character 接口类型:

¥For example, you could have a Character Interface type that represents any character in the Star Wars trilogy:

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}

这意味着任何实现 Character 的类型都需要具有这些精确的字段以及相同的参数和返回类型。

¥This means that any type that implements Character needs to have these exact fields as well as the same arguments and return types.

例如,以下是一些可能实现 Character 的类型:

¥For example, here are some types that might implement Character:

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}
 
type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  primaryFunction: String
}

你可以看到,这两种类型都具有 Character 接口类型的所有字段,但也引入了特定于该特定类型字符的额外字段 - totalCreditsstarshipsprimaryFunction

¥You can see that both of these types have all of the fields from the Character Interface type, but also bring in extra fields—totalCredits, starships and primaryFunction—that are specific to that particular type of character.

当你想要返回一个对象或一组对象时,接口类型很有用,但这些对象可能有几种不同的类型。例如,请注意以下查询会产生错误:

¥Interface types are useful when you want to return an object or set of objects, but those might be of several different types. For example, note that the following query produces an error:

Operation
Response

hero 字段返回类型 Character,这意味着它可能是 HumanDroid,具体取决于 episode 参数。在上面的查询中,你只能询问 Character 接口类型上存在的字段,不包括 primaryFunction

¥The hero field returns the type Character, which means it might be either a Human or a Droid depending on the episode argument. In the query above, you can only ask for fields that exist on the Character Interface type, which doesn’t include primaryFunction.

要请求特定对象类型的字段,你需要使用 内联片段

¥To ask for a field on a specific Object type, you need to use an inline fragment:

Operation
Response

接口类型也可以实现其他接口类型:

¥Interface types may also implement other Interface types:

interface Node {
  id: ID!
}
 
interface Character implements Node {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}

请注意,接口类型可能无法实现自身或包含任何相互循环引用。

¥Note that Interface types may not implement themselves or contain any cyclic references to each other.

While types may share common fields in a GraphQL API, that may not always warrant the use of an Interface type to enforce that those fields remain consistently named. Interface types are a powerful way to indicate shared behavior across the types that implement them. When used, they should be semantically meaningful to client developers, just like Character is a useful abstraction for humans and droids.

联合类型

¥Union types

GraphQL 支持第二种抽象类型,称为 联合类型。联合类型与接口类型有相似之处,但它们不能在组成类型之间定义任何共享字段。

¥GraphQL supports a second abstract type called a Union type. Union types share similarities with Interface types, but they cannot define any shared fields among the constituent types.

联合类型通过指示其成员对象类型来定义:

¥A Union type is defined by indicating its member Object types:

union SearchResult = Human | Droid | Starship

无论我们在结构中返回 SearchResult 类型,我们都可能得到 HumanDroidStarship。请注意,联合类型的成员需要是具体的对象类型;你不能使用接口类型或其他联合类型作为成员来定义一个。

¥Wherever we return a SearchResult type in our schema, we might get a Human, a Droid, or a Starship. Note that members of a Union type need to be concrete Object types; you can’t define one using Interface types or other Union types as members.

在这种情况下,如果你查询返回 SearchResult Union 类型的字段,则需要使用 内联片段 才能查询在成员 Object 类型上定义的任何字段:

¥In this case, if you query a field that returns the SearchResult Union type, you need to use an inline fragment to be able to query any fields that are defined on the member Object types:

Operation
Response

__typename 字段是一个特殊的元字段,它自动存在于每个对象类型上并解析为该类型的名称,从而提供一种区分客户端数据类型的方法。

¥The __typename field is a special meta-field that automatically exists on every Object type and resolves to the name of that type, providing a way to differentiate between data types on the client.

此外,在这种情况下,由于 HumanDroid 共享一个公共接口 (Character),你可以在一个地方查询它们的公共字段并仍然获得相同的结果:

¥Also, in this case, since Human and Droid share a common interface (Character), you can query their common fields in one place and still get the same result:

Operation
Response

请注意,name 仍然在 Starship 上指定,因为否则它不会显示在结果中,因为 Starship 不是 Character

¥Note that name is still specified on Starship because otherwise it wouldn’t show up in the results given that Starship is not a Character!

输入对象类型

¥Input Object types

我们在本页介绍的大多数示例都演示了对象、标量、枚举、接口和联合类型如何用作架构中字段的输出类型。但我们还看到字段参数必须指定它们的输入类型。

¥Most of the examples we’ve covered on this page demonstrate how Object, Scalar, Enum, Interface, and Union types may be used as output types for the fields in a schema. But we have also seen that field arguments must specify their input types.

到目前为止,我们仅讨论了使用标量值(如枚举或字符串类型)作为字段参数的输入类型。但是,你也可以使用 输入对象类型 将复杂对象作为参数传递,这是我们将要探索的最后一种 GraphQL 命名类型。

¥So far, we’ve only talked about using scalar values (like Enums or String types) as an input type for a field argument. However, you can also pass complex objects as arguments using an Input Object type, which is the last kind of named types in GraphQL that we’ll explore.

这在 mutations 的情况下尤其有价值,你可能希望传入要创建的整个对象。在 SDL 中,输入对象类型看起来类似于常规对象类型,但使用关键字 input 而不是 type

¥This is particularly valuable in the case of mutations, where you might want to pass in a whole object to be created. In SDL, Input Object types look similar to regular Object types, but with the keyword input instead of type:

input ReviewInput {
  stars: Int!
  commentary: String
}
 
type Mutation {
  createReview(episode: Episode, review: ReviewInput!): Review
}

以下是如何在突变中使用输入对象类型:

¥Here is how you could use the Input Object type in a mutation:

Operation
Response

输入对象类型上的字段可以引用其他输入对象类型,但你不能在架构中混合输入和输出类型。输入对象类型也不能在其字段上有参数。

¥The fields on an Input Object type can refer to other Input Object types, but you can’t mix input and output types in your schema. Input Object types also can’t have arguments on their fields.

指令

¥Directives

在字段参数不足或某些常见行为必须在多个位置复制的某些情况下,directives 允许我们使用 @ 字符后跟指令的名称来修改 GraphQL 模式或操作的部分内容。

¥In certain instances where field arguments are insufficient or certain common behaviors must be replicated in multiple locations, directives allow us to modify parts of a GraphQL schema or operation by using an @ character followed by the directive’s name.

类型系统指令允许我们注释模式中的类型、字段和参数,以便可以以不同的方式验证或执行它们。

¥Type system directives allow us to annotate the types, fields, and arguments in a schema so that they may be validated or executed differently.

指令也可以定义为可执行指令以用于 GraphQL 操作。阅读有关查询页面上的可执行指令的更多信息。

¥Directives may also be defined for use in GraphQL operations as executable directives. Read more about executable directives on the Queries page.

GraphQL 规范定义了几个 内置指令。例如,对于支持 SDL 的实现,@deprecated 指令将可用于注释架构中已弃用的部分:

¥The GraphQL specification defines several built-in directives. For example, for implementations that support SDL, the @deprecated directive will be available to annotate deprecated parts of the schema:

type User {
  fullName: String
  name: String @deprecated(reason: "Use `fullName`.")
}

虽然如果你使用的是支持 SDL 的 GraphQL 实现,则无需在架构中明确定义 @deprecated 指令,但其底层定义如下所示:

¥While you won’t need to define the @deprecated directive in your schema explicitly if you’re using a GraphQL implementation that supports SDL, it’s underlying definition would look like this:

directive @deprecated(
  reason: String = "No longer supported"
) on FIELD_DEFINITION | ENUM_VALUE

请注意,就像字段一样,指令可以接受参数,并且这些参数可以具有默认值。@deprecated 指令具有可空的 reason 参数,该参数接受 String 作为输入类型并回退到 "No longer supported"。对于指令,我们必须指定它们可以在何处使用,例如在 @deprecated 指令的 FIELD_DEFINITIONENUM_VALUE 上。

¥Note that, just like fields, directives can accept arguments and those arguments can have default values. The @deprecated directive has a nullable reason argument that accepts a String as an input type and falls back to "No longer supported". And with directives, we must specify where they may be used, such as on a FIELD_DEFINITION or ENUM_VALUE for the @deprecated directive.

除了 GraphQL 的内置指令外,你还可以定义自己的自定义指令。与自定义标量类型一样,由你选择的 GraphQL 实现决定如何在查询执行期间处理自定义指令。

¥In addition to GraphQL’s built-in directives, you may define your own custom directives. As with custom Scalar types, it’s up to your chosen GraphQL implementation to determine how to handle custom directives during query execution.

文档

¥Documentation

描述

¥Descriptions

GraphQL 允许你向架构中的类型、字段和参数添加文档。事实上,GraphQL 规范鼓励你在所有情况下都这样做,除非类型、字段或参数的名称是自描述的。架构描述使用 Markdown 语法定义,可以是多行或单行。

¥GraphQL allows you to add documentation to the types, fields, and arguments in a schema. In fact, the GraphQL specification encourages you to do this in all cases unless the name of the type, field, or argument is self-descriptive. Schema descriptions are defined using Markdown syntax and can be multiline or single line.

在 SDL 中,它们看起来像这样:

¥In SDL, they would look like this:

"""
A character from the Star Wars universe
"""
type Character {
  "The name of the character."
  name: String!
}
 
"""
The episodes in the Star Wars trilogy
"""
enum Episode {
  "Star Wars Episode IV: A New Hope, released in 1977." 
  NEWHOPE
  "Star Wars Episode V: The Empire Strikes Back, released in 1980."
  EMPIRE
  "Star Wars Episode VI: Return of the Jedi, released in 1983."
  JEDI
}
 
"""
The query type, represents all of the entry points into our object graph
"""
type Query {
  """
  Fetches the hero of a specified Star Wars film.
  """
  hero(
    "The name of the film that the hero appears in."
    episode: Episode
  ): Character
}

除了使 GraphQL API 模式更具表现力之外,描述对客户端开发者也很有帮助,因为它们在 自省查询 中可用,并且在 GraphiQL 等开发者工具中可见。

¥In addition to making a GraphQL API schema more expressive, descriptions are helpful to client developers because they are available in introspection queries and visible in developer tools such as GraphiQL.

注释

¥Comments

有时,你可能需要在架构中添加注释,这些注释不描述类型、字段或参数,并且不打算让客户端看到。在这些情况下,你可以通过在文本前面加上 # 字符来向 SDL 添加单行注释:

¥Occasionally, you may need to add comments in a schema that do not describe types, fields, or arguments, and are not meant to be seen by clients. In those cases, you can add a single-line comment to SDL by preceding the text with a # character:

# This line is treated like whitespace and ignored by GraphQL
type Character {
  name: String!
}

还可以向客户端查询添加注释:

¥Comments may also be added to client queries:

Operation
Response

后续步骤

¥Next steps

回顾我们学到的关于查询的知识:

¥To recap what we’ve learned about schemas and types:

  • 根据选择哪个库来构建 GraphQL 服务,我们可以使用 SDL 以与语言无关的方式定义模式,或者通过从为其字段提供数据的代码中编译模式

    ¥Depending on what library is selected to build a GraphQL service, we can define a schema in a language-agnostic way using SDL or by compiling the schema from the code that provides data for its fields

  • GraphQL 中有六种命名类型定义:对象、标量、枚举、接口、联合和输入对象类型

    ¥There are six kinds of named type definitions in GraphQL: Object, Scalar, Enum, Interface, Union, and Input Object types

  • 对象类型包含指定输出类型的字段,这些字段可能具有指定输入类型的参数

    ¥Object types contain fields that specify output types, and those fields may have arguments that specify input types

  • IntFloatStringBooleanID 标量类型内置于 GraphQL 中,你也可以定义自己的自定义标量

    ¥The IntFloatStringBoolean, and ID Scalar types are built into GraphQL, and you can also define your own custom scalars

  • 与标量类型一样,枚举类型表示 GraphQL 模式中的叶值,但它们仅限于一组有限的值

    ¥Like Scalar types, Enum types represent leaf values in a GraphQL schema but they are limited to a finite set of values

  • List ([]) 和非空 (!) 类型修饰符允许你更改字段的输出类型或参数的输入类型的默认行为

    ¥The List ([]) and Non-Null (!) type modifiers allow you to change the default behavior for a field’s output type or argument’s input type

  • 接口和联合类型是抽象类型,允许从单个字段输出不同的具体对象类型

    ¥Interface and Union types are abstract types that allow different concrete Object types to be output from a single field

  • 输入对象类型允许你将比标量和枚举类型允许的更复杂的值传递到字段参数或指令参数中

    ¥Input Object types allow you to pass more complex values into a field argument or directive argument than Scalar and Enum types allow

  • 类型系统指令可以应用于模式中的类型、字段和参数,以改变它们在查询期间的验证和执行方式

    ¥Type system directives can be applied to the types, fields, and arguments in a schema to alter how they are validated and executed during a query

  • GraphQL 支持使用类型、字段和参数描述的模式文档,并且还支持被解析器忽略的注释

    ¥GraphQL supports schema documentation using type, field, and argument descriptions, and it also supports comments that are ignored by the parser

现在你了解了类型系统的主要功能,你已准备好了解有关如何 从 GraphQL API 查询数据 的更多信息。

¥Now that you understand the key features of the type system, you’re ready to learn more about how to query data from a GraphQL API.