跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

深入浅析GraphQL类型系统

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
:非空布尔类型。 在声明上方,可以使用双引号添加注释,如本例:
具有直接战斗能力和力量的英雄
,这将显示为类型的描述。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 在此示例中,每个字段都解析为标量类型,但对象字段也可以解析为其他对象类型。例如,可以创建一个
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视频教程 、 编程教学 】

相关文章