
graphql 最初于 2012 年在 facebook 开发,作为针对动力不足的移动设备的更好的数据获取尊龙凯时的解决方案,graphql 于 2015 年开源。作为一种为灵活性而设计的 api 技术,graphql 是 api 的开发人员和消费者以及他们背后的组织的强大推动者。graphql 实现的所有细节和功能都在 graphql schema 中列出。为了编写一个有效的 graphql schema,必须理解好 graphql 类型系统。
在本文中,将学习 graphql 类型:五种内置标量(scalar)类型、枚举(enums)、列表(list)和非空包装(non-null)类型、对象(object)类型以及与它们一起工作的抽象接口和联合类型(union)。
标量类型
graphql 模式中的所有数据最终都解析为各种标量类型,代表原始值。graphql 响应可以看作一棵树,标量类型是树末端的叶子。嵌套响应中可以有多个级别,但最后一个级别将始终解析为标量(或枚举)类型。 graphql 带有五种内置标量类型:int、float、string、boolean 和 id。
int
int 是带符号的 32 位非小数值,它是不包括小数的带符号(正或负)整数。带符号的 32 位整数的最大值为 2,147,483,647。这是用于数值数据的两个内置标量之一。
float
float 是带符号的双精度小数值。它是一个带小数点的有符号(正或负)数,例如 1.2,这是用于数值数据的另一个内置标量。
string
string 是 utf-8 字符序列。 string 类型用于任何文本数据,这也可以包括非常大的数字等数据。大多数自定义标量都是字符串数据类型。
boolean
boolean 包含 true 和 false。
id
id 是唯一标识符,始终序列化为字符串,即使 id 是数字也是如此。id 类型通常可以用通用唯一标识符 (uuid) 表示。
自定义标量
除了上述这些内置标量之外,还可以使用 scalar 关键字来定义自定义标量。可以使用自定义标量来创建具有额外服务器级别验证的类型,例如 date、time 或 url。下面是一个定义新 date 类型的示例:
scalar date
服务器将知道如何使用 graphqlscalartype 处理与这种新类型的交互。
枚举(enum)类型
enum 类型,也称为 enumerator 类型,用于描述了一组可能的值。
例如可以为游戏角色的 job 和 species 创建一个枚举,其中包含系统将接受的所有值。
"角色的工作等级"
enum job {
fighter
wizard
}
"性格的种类或血统"
enum species {
human
elf
dwarf
}通过定义枚举类型可以保证角色的 job 只能是 fighter 或 wizard,并且永远不会意外地成为其他一些随机字符串,如果使用 string 类型而不是 enum,那么就有可能是别的随机字符串。
枚举也可以用作参数中的可接受值。例如,可以制作一个 hand 枚举来表示武器是单手(如短剑)还是双手(如重斧),并使用它来确定是否可以装备一个或两个:
enum hand { single
double}"战士使用的一种武器"type weapon {
name: string!
attack: int
range: int
hand: hand
}
type query {
weapons(hand: hand = single): [weapon]
}hand 枚举已声明为 single 和 double 作为值,weapons 字段上的参数具有默认值 single,这意味着如果未传递任何参数,它将回默认为 single。
非空类型
可能会注意到内置标量列表中缺少 null 或 undefined(一种被许多语言视为原始类型的常见类型)。 null 在 graphql 中确实存在,表示缺少一个值。默认情况下,graphql 中的所有类型都可以为 null,因此 null 是对任何类型的有效响应。为了使值成为必需值,必须将其转换为带有尾随感叹号的 graphql 非空类型。 non-null 被定义为类型修饰符,这些类型用于修饰它所引用的类型。例如,string 是一个可选的(或可为空的)字符串,而 string! 是必需的(或非空的)字符串。
列表类型
graphql 中的 list 类型是另一种类型修饰符。任何用方括号 ([]) 括起来的类型都会成为 list 类型,这是一个定义列表中每个项目类型的集合,像 javascript 中的数组。
例如,定义为 [int] 的类型意味着这个集合所有元素的类型为 int 类型,[string] 将是 string 类型的集合。 non-null 和 list 可以一起使用,使一个类型既需要又定义为 list,例如 [string]!。
对象类型
如果 graphql 标量类型描述分层 graphql 响应末尾的“叶子”,那么对象类型描述中间的 分支,并且 graphql 模式中的几乎所有内容都是一种对象类型。
对象由命名字段(键)列表和每个字段将解析为的值类型组成。对象是用 type 关键字定义的。至少要定义一个或多个字段,字段不能以两个下划线(__)开头,以免与graphql自省系统冲突。
例如创建一个 fighter 对象来表示游戏中的一种角色:
"具有直接战斗能力和力量的英雄"
type fighter {
id: id!
name: string!
level: int
active: boolean!
}在此示例中,声明了 fighter 对象类型,定义了 4 个字段:
id:非空id类型。name:非空字符串类型。level:int类型。active:非空布尔类型。
在声明上方,可以使用双引号添加注释,如本例:具有直接战斗能力和力量的英雄,这将显示为类型的描述。
在此示例中,每个字段都解析为标量类型,但对象字段也可以解析为其他对象类型。例如,可以创建一个 weapon 类型,并且可以设置 graphql 模式,其中 fighter 上的 weapon 字段将解析为一个 weapon 对象:
"战士使用的一种武器"
type weapon {
name: string!
attack: int
range: int
}
"具有直接战斗能力和力量的英雄"
type fighter {
id: id!
name: string!
level: int
active: boolean!
weapon: weapon
}对象也可以嵌套到其他对象的字段中。
根操作类型
有三种特殊对象作为 graphql schema 的入口点:query、mutation 和 subcription。这些被称为根操作类型,并遵循与任何其他对象类型相同的规则。
schema 关键字表示 graphql 模式的入口点。根 query、mutation 和 subcription 类型将位于根模式对象上:
schema {
query: query
mutation: mutation
subscription: subscription
}query 类型在任何 graphql 模式上都是必需的,代表一个读取请求,类似于 rest api get。以下是返回 fighter 类型列表的根查询对象的示例:
type query {
fighters: [fighter]
}mutations 代表写入请求,类似于 rest api 中的 post、put 或 delete。在以下示例中,mutation 有一个带有命名参数(输入)的 addfighter 字段:
type mutation {
addfighter(input: fighterinput): fighter
}最后,一个 subscription 对应于一个事件流,它将与 web 应用程序中的 websocket 结合使用。如下所示:
type subscription {
randombattle(enemy: enemy): battleresult
}请注意,schema 入口点通常在某些 graphql 实现中被抽象掉。
字段参数
graphql 对象的字段本质上是返回值的函数,并且它们可以像任何函数一样接受参数。字段参数由参数名称后跟类型定义,参数可以是任何非对象类型。在此示例中,可以通过 id 字段(解析为非空 id 类型)过滤 fighter 对象:
type query {
fighter(id: id!): fighter
}这个特定示例对于从数据存储中获取单个项目很有用,但参数也可用于过滤、分页和其他更具体的查询。
接口类型
与 object 类型一样,抽象接口类型由一系列命名字段及其关联的值类型组成。接口看起来像并遵循与对象相同的所有规则,但用于定义对象实现的子集。
到目前为止,在 schema 中有一个 fighter 对象,但可能还想创建一个wizard、一个 healer 和其他对象,它们将共享大部分相同的字段但还是存在一些差异。在这种情况下,可以使用接口来定义它们共有的字段,并创建作为接口实现的对象。
在下面的示例中,使用 interface 关键字创建 basecharacter 接口,其中包含每种类型的字符将拥有的所有字段:
"a hero on a quest."interface basecharacter {
id: id!
name: string!
level: int!
species: species
job: job
}每个角色类型都有字段 id、name、level、species 和 job。
现在,假设有一个具有这些共享字段的 fighter 类型和一个 wizard 类型,但是 fighters 使用 weapon 而 wizards 使用 spells。可以使用 implements 关键字将每个描述为 basecharacter 实现,这意味着它们必须具有创建的接口中的所有字段:
type fighter implements basecharacter {
id: id!
name: string!
level: int!
species: species
job: job!
weapon: weapon
}
type wizard implements basecharacter {
id: id!
name: string!
level: int!
species: species
job: job!
spells: [spell]
}fighter 和 wizard 都是 basecharacter 接口的有效实现,因为它们具有所需的字段子集。
union 类型
可以与对象一起使用的另一种抽象类型是 union 类型。使用 union 关键字,可以定义一个类型,其中包含所有有效响应的对象列表。
使用上面创建的接口,可以创建一个 character union,将 character 定义为 wizard 或 fighter :
union character = wizard | fighter
等号 = 设置定义,管道符 | 用作 or 语句。请注意,union 必须由对象或接口组成,标量类型在 union 上无效。
现在,如果查询 characters 列表,它可以使用 character union 并返回所有 wizard 和 fighter 类型。
总结
上面学习了定义 graphql 类型系统的类型,包括最基本的类型是标量类型由 int、float、string、boolean、id和 graphql 实现创建的任何自定义标量类型组成。枚举是有效常量值的列表,当需要对查询响应进行更多控制时,可以使用枚举,而不是简单地将其声明为字符串。列表类型和非空类型被称为类型修饰符 type modifier 或包装类型 wrapping type,它们分别可以将其他类型定义为集合类型或必需类型。graphql schema 中的几乎所有内容都是对象类型,包括 query、mutation 和 subscription 入口点。接口和联合类型是抽象类型,在定义对象时很有用。
【相关推荐:go视频教程、编程教学】
以上就是深入浅析graphql类型系统的详细内容,更多请关注其它相关文章!
小小无邪控