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
是帶符號的32
位元非小數值,它是不包含小數的帶符號(正或負)整數。帶符號的 32
位元整數的最大值為 2,147,483,647
。這是用於數值資料的兩個內建標量之一。
Float
是帶符號的雙精確度小數值。它是一個帶有小數點的符號(正或負)數,例如 1.2
,這是用於數值資料的另一個內建標量。
String
是 UTF-8
字元序列。 String
類型用於任何文字數據,這也可以包括非常大的數字等數據。大多數自訂標量都是字串資料類型。
Boolean
包含 true
和 false
。
ID
是唯一標識符,始終序列化為字串,即使ID
是數字也是如此。 ID
類型通常可以用通用唯一識別碼 (UUID) 表示。
除了上述這些內建標量之外,還可以使用 scalar
關鍵字來定義自訂標量。可以使用自訂標量來建立具有額外伺服器層級驗證的類型,例如 Date
、Time
或 Url
。以下是定義新 Date
類型的範例:
scalar Date
伺服器將知道如何使用 GraphQLScalarType 處理與這個新類型的互動。
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
关键字,可以定义一个类型,其中包含所有有效响应的对象列表。
使用上面创建的接口,可以创建一个 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
入口点。接口和联合类型是抽象类型,在定义对象时很有用。
以上是深入淺析GraphQL型系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!