现在,服务的GraphQL模式通常使用称为GraphQL SDL(模式定义语言)的语言指定,有时也称为GraphQL模式语言。它是一种语法非常简单的语言,允许非常简洁地定义模式。一旦您对SDL的不同语法元素略知一二,您就可以轻而易举地编写模式了。
基础知识
以下是一个简单TODO应用程序的基本GraphQL模式定义:
1# Enumeration type for a level of priority
2enum Priority {
3 LOW
4 MEDIUM
5 HIGH
6}
7
8# Our main todo type
9type Todo {
10 id: ID!
11 name: String!
12 description: String
13 priority: Priority!
14}
15
16type Query {
17 # Get one todo item
18 todo(id: ID!): Todo
19 # Get all todo items
20 allTodos: [Todo!]!
21}
22
23type Mutation {
24 addTodo(name: String!, priority: Priority = LOW): Todo!
25 removeTodo(id: ID!): Todo!
26}
27
28schema {
29 query: Query
30 mutation: Mutation
31}
这里发生了很多事情,所以让我们来分析一些最重要的事情:
对象类型
对象类型特定于GraphQL服务,使用TYPE关键字定义,按照惯例以大写字母开头。它们定义类型名称和该类型下显示的字段。对象类型中的每个字段都可以解析为其他对象类型或标量类型。标量类型指向实际数据并表示图形的叶子。
在上面的模式定义中,我们有TODO对象类型以及查询和突变根对象类型。所有GraphQL模式中只需要查询根类型,但当服务允许更新、添加或删除数据时,突变根类型通常也会出现。此外,还可以使用订阅根类型来定义客户端可以订阅的操作。
内置标量类型
GraphQL内置了5种标量类型:INT、FLOAT、STRING、Boolean和ID。相对于对象类型,标量类型指向实际数据。ID类型解析为字符串,但需要唯一的值。
枚举类型
枚举类型允许为类型定义可能值的特定子集。在前面的示例中,优先级枚举类型可以采用低、中或高的值,其他任何值都将导致验证错误。在客户端,字符串用于提供枚举类型的值。
类型修饰符
正如您从上面的示例中也可以看到的,可以通过使用以下字符在字段解析为的类型上使用修饰符!和[...]。以下是使用字符串标量类型作为示例的细目:
- String:可以为空的字符串(解析后的值可以为空)
- STRING!:不可为空的字符串(如果解析的值为空,则会抛出错误)
- [字符串]:可为空的字符串值的可空列表。整个值可以为空,或者特定的列表元素可以为空。
- [字符串!]:不可为空的字符串值的可空列表。则整个值可以为空,但特定列表元素不能为空。
- [字符串!]!:不可为空的字符串值列表。任何内容都不能为空,既不能是整个值,也不能是单个项。空列表([])仍然有效,因为整个值不为NULL,并且没有单独的NULL值。
评论
添加的注释带有# 符号,并且只允许单行注释。
自定义标量类型
也可以使用如下语法定义自定义标量类型:
1scalar DateTime
尽管如此,GraphQL服务将需要定义如何序列化和验证定制标量。
联合类型
联合类型定义可以解析为多种可能的对象类型的类型:
1# ...
2
3union Vehicule = Car | Boat | Plane
4
5type Query {
6 getVehicule(id: ID!): Vehicule!
7}
对于联合类型,在客户端上,必须使用内联fragments来根据要解析的子类型选择所需的字段:
1query {
2 getVehicule {
3 ...on Car {
4 year
5 }
6 ...on Boat {
7 color
8 }
9 ...on Plane {
10 seating
11 }
12 }
13}
接口
接口有点类似于联合类型,但它们允许多个对象类型共享某些字段:
1interface Vehicule {
2 color: String
3 make: String
4 speed: Int
5}
6
7type Car implements Vehicule {
8 color: String
9 make: String
10 speed: Int
11 model: String
12}
13
14# ...
实现接口的每种类型都需要有与接口的所有字段相对应的字段,但也可以有自己的附加字段。这样,在客户机上,可以使用内联片段来获取特定类型唯一的字段:
1graphql {
2 getVehicule {
3 color
4 make
5 ...on Car {
6 model
7 }
8 }
9}
输入类型
当查询或突变需要多个参数时,可以更容易地定义输入类型,其中每个字段表示一个参数:
1# ...
2
3input NewTodoInput {
4 name: String!
5 priority: Priority = LOW
6}
7
8type Mutation {
9 addTodo(newTodoInput: NewTodoInput!): Todo!
10 removeTodo(id: ID!): Todo!
11}
方案文档
还有一种语法可以为类型和字段添加人类可读的文档,当使用GraphiQL或GraphQL Playground]这样的工具浏览模式的文档时,这会变得非常有用。
让我们以最初的TODO模式示例为例,添加一些有关类型和一些字段的文档:
1"""
2Priority level
3"""
4enum Priority {
5 LOW
6 MEDIUM
7 HIGH
8}
9
10type Todo {
11 id: ID!
12 name: String!
13 """
14 Useful description for todo item
15 """
16 description: String
17 priority: Priority!
18}
19
20"""
21Queries available on the todo app service
22"""
23type Query {
24 """
25 Get one todo item
26 """
27 todo(id: ID!): Todo
28 """
29 List of all todo items
30 """
31 allTodos: [Todo!]!
32}
33
34type Mutation {
35 addTodo(
36 "Name for the todo item"
37 name: String!
38 "Priority levl of todo item"
39 priority: Priority = LOW): Todo!
40 removeTodo(id: ID!): Todo!
41}
42
43schema {
44 query: Query
45 mutation: Mutation
46}
如您所见,类型或字段的文档是通过使用* ...``* 语法添加的。*
...`* 用于参数文档。
有了这些,您应该可以开始使用定义GraphQL模式的竞赛了。当您对某些语法不确定时,也可以随时参考官方spec]。