作者選擇了自由和開放源代碼基金作為Write for DOnations計劃的一部分進行捐贈。
介紹
GraphQL是促進前端與數據源通信的現代解決方案。所有關於GraphQL實現的細節和能力都在GraphQL Schema中明確列出。為了編寫一個有效的GraphQL模式,您必須理解GraphQL類型系統。
在本文中,您將了解GraphQL類型:五種內置的標量類型、枚舉、列表和非空包裹類型、對象類型,以及與它們一起工作的抽象接口和聯合類型。您將查看每種類型的示例,並學習如何使用它們來構建完整的GraphQL模式。
先決條件
為了充分利用本教程,您應該具備:
- 對 GraphQL 的基本概念有一定的了解,這些概念在《GraphQL 簡介》中有詳細介紹。GraphQL 簡介。
- A GraphQL environment, an example of which can be found in How to Set Up a GraphQL API Server in Node.js.
純量類型
GraphQL 模式中的所有數據最終都解析為不同的 純量 類型,這些類型代表原始值。 GraphQL 響應可以表示為樹,而純量類型是樹末端的葉子。 嵌套響應可以有多個級別,但最後一級始終解析為純量(或枚舉)類型。 GraphQL 預設提供了五種內置的純量類型:Int
、Float
、String
、Boolean
和 ID
。
Int
Int
是一個帶符號的32位非小數數值。它是一個帶符號(正或負)的整數,不包括小數部分。帶符號32位整數的最大值是 2,147,483,647
。這是用於數值數據的兩種內置純量之一。
Float
A Float
is a signed double-precision fractional value. It is a signed (positive or negative) number that contains a decimal point, such as 1.2
. This is the other built-in scalar used for numerical data.
String
A String
is a UTF-8 character sequence. The String
type is used for any textual data. This can also include data like very large numbers. Most custom scalars will be types of string data.
Boolean
A Boolean
is a true
or false
value.
ID
一個ID
是一個唯一的標識符。該值始終被序列化為字符串,即使ID
是數值。ID
類型可能通常用通用唯一標識符(UUID)來表示。
自訂標量
除了這些內建的標量之外,標量
關鍵字可以用來定義自訂標量。您可以使用自訂標量來創建具有額外伺服器級驗證的類型,例如 日期
、時間
或 網址
。以下是定義新 日期
類型的示例:
scalar Date
伺服器將知道如何使用 GraphQLScalarType
處理與此新類型的互動。
列舉類型
列舉 類型,又稱為 列舉器 類型,描述一組可能的值。
使用來自 如何使用 GraphQL 管理資料 系列其他教程中的幻想遊戲 API 主題,您可以為遊戲角色的 職業
和 物種
創建一個包含系統接受的所有值的 enum
。列舉型別使用 enum
關鍵字定義,如下所示:
"The job class of the character."
enum Job {
FIGHTER
WIZARD
}
"The species or ancestry of the character."
enum Species {
HUMAN
ELF
DWARF
}
在这种方式下,确保角色的Job
是FIGHTER
或WIZARD
,永远不会意外地变成"purple"
或其他随机字符串,如果使用String
类型而不是自定义的枚举类型可能会发生。枚举类型通常按照惯例使用全大写字母编写。
枚举类型还可以用作参数的接受值。例如,您可以创建一个Hand
enum
来表示武器是单手的(如短剑)还是双手的(如重斧),并使用它来确定是否可以装备一个或两个:
enum Hand {
SINGLE
DOUBLE
}
"A valiant weapon wielded by a fighter."
type Weapon {
name: String!
attack: Int
range: Int
hand: Hand
}
type Query {
weapons(hand: Hand = SINGLE): [Weapon]
}
已使用SINGLE
和DOUBLE
作为Hand
enum
的值,并且weapons
字段上的参数具有SINGLE
的默认值,这意味着如果没有传递参数,它将回退为SINGLE
。
非空类型
您可能注意到null
或undefined
,许多语言视为原始类型的常见类型,在内置标量列表中是缺失的。 Null 在GraphQL中存在,表示缺乏值。
所有GraphQL中的類型都默認可為空,因此null
對於任何類型都是有效的響應。為了使值成為必需,必須將其轉換為帶有尾部感歎號的GraphQL非空類型。非空被定義為類型修飾符,這些類型用於修改它所引用的類型。例如,String
是可選(或可為空)字符串,而String!
是必需(或非空)字符串。
列表類型
A List type in GraphQL is another type modifier. Any type that is wrapped in square brackets ([]
) becomes a List type, which is a collection that defines the type of each item in a list.
例如,定義為[Int]
的類型將是Int
類型的集合,而[String]
將是String
類型的集合。非空和列表可以一起使用,使類型既是必需的又定義為列表,例如[String]!
。
對象類型
如果GraphQL純量類型描述了層次化GraphQL響應末端的“葉子”,則對象類型描述了中介的“分支”,幾乎所有GraphQL模式中的內容都是對象類型。
對象由一系列命名字段(鍵)和每個字段將解析為的值類型組成。對象使用type
關鍵字定義。必須定義至少一個或多個字段,且字段不能以兩個下劃線(__
)開頭,以避免與GraphQL內省系統衝突。
在GraphQL Fantasy Game API示例中,您可以創建一個Fighter
對象來表示遊戲中的一種角色類型:
"A hero with direct combat ability and strength."
type Fighter {
id: ID!
name: String!
level: Int
active: Boolean!
}
在這個例子中,Fighter
對象類型已經聲明,並且它有四個命名字段:
id
產生一個非空的ID
類型。name
產生一個非空的String
類型。level
產生一個Int
類型。active
產生一個非空的Boolean
類型。
在聲明之上,您還可以使用雙引號添加評論,就像這個例子中的"A hero with direct combat ability and strength."
一樣。這將顯示為類型的描述。
在這個例子中,每個字段解析為純量類型,但對象字段也可以解析為其他對象類型。例如,您可以創建一個Weapon
類型,並且GraphQL模式可以設置,其中Fighter
上的weapon
字段將解析為Weapon
對象:
"A valiant weapon wielded by a fighter."
type Weapon {
name: String!
attack: Int
range: Int
}
"A hero with direct combat ability and strength."
type Fighter {
id: ID!
name: String!
level: Int
active: Boolean!
weapon: Weapon
}
對象也可以嵌套到其他對象的字段中。
根操作類型
有三種特殊的物件充當 GraphQL 架構的入口點:Query、Mutation 和 Subscription。這些被稱為根操作類型,並遵從任何其他物件類型的相同規則。
schema
關鍵字表示進入 GraphQL 架構的入口點。您的根 Query、Mutation 和 Subscription 類型將位於根 schema
物件中:
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
Query 類型是任何 GraphQL 架構中必需的,代表一個讀取請求,類似於 REST API 中的 GET
。以下是一個根 Query
物件的示例,它返回一個 Fighter
類型的列表:
type Query {
fighters: [Fighter]
}
Mutations 代表一個寫入請求,類似於 REST API 中的 POST
、PUT
或 DELETE
。在以下示例中,Mutation
具有一個帶有命名參數(input
)的 addFighter
字段:
type Mutation {
addFighter(input: FighterInput): Fighter
}
最後,Subscription 對應到一個事件流,可以與 Web 應用程式中的 Websocket 一起使用。在 GraphQL Fantasy API 中,也許可以用於隨機戰鬥遭遇,如下所示:
type Subscription {
randomBattle(enemy: Enemy): BattleResult
}
請注意,schema
入口點在某些 GraphQL 實現中通常被抽象化。
字段參數
GraphQL 物件的字段本質上是返回值的函數,它們可以像任何函數一樣接受參數。 字段參數由參數名稱和類型組成。參數可以是任何非物件類型。在此示例中,Fighter
物件可以通過 id
字段進行篩選(解析為非空 ID
類型):
type Query {
fighter(id: ID!): Fighter
}
這個特定的示例用於從數據存儲中提取單個項目,但參數也可以用於篩選、分頁和其他更具體的查詢。
介面類型
與物件類型一樣,抽象的 介面類型由一組命名字段及其相關的值類型組成。介面看起來和遵循與物件相同的所有規則,但用於定義物件實現的子集。
到目前為止,在你的架構中,你有一個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
的實現,這意味著它們必須具有從所創建的介面繼承的所有欄位:
"A hero with direct combat ability and strength."
type Fighter implements BaseCharacter {
id: ID!
name: String!
level: Int!
species: Species
job: Job!
weapon: Weapon
}
"A hero with a variety of magical powers."
type Wizard implements BaseCharacter {
id: ID!
name: String!
level: Int!
species: Species
job: Job!
spells: [Spell]
}
Fighter
和Wizard
都是BaseCharacter
介面的有效實現,因為它們具有所需的欄位子集。
Union Type
另一個可以與對象一起使用的抽象類型是 Union 類型。使用 union
關鍵字,您可以定義一個包含一組對象的類型,這些對象都可以作為響應的有效值。
使用上一節中創建的接口,您可以創建一個 Character
Union,將字符定義為 Wizard
或 Fighter
:
union Character = Wizard | Fighter
等號字符(=
)設置定義,管道字符(|
)作為 OR
聲明。請注意,聯合必須由對象或接口組成。純量類型在聯合中無效。
現在,如果您查詢字符列表,它可以使用 Character
聯合並返回所有 Wizard
和 Fighter
類型。
結論
在這個教程中,你學到了許多定義 GraphQL 類型系統 的類型。最基本的類型是標量類型,它們是模式樹上的葉子,包括 Int
、Float
、String
、Boolean
、ID
,以及 GraphQL 實現決定創建的任何自定義標量。列舉是有效常數值的列表,當你需要對響應進行更多控制而不僅僅宣告它為 String
時可以使用,它們也是模式樹上的葉子。列表和非空類型被稱為類型修改器,或包裝類型,它們可以定義其他類型作為集合或必需的。對象是模式樹的分支,幾乎在 GraphQL 模式中的每件事物都是對象的一種類型,包括 query
、mutation
和 subscription
入口點。接口和聯合類型是抽象類型,對於定義對象很有幫助。
為了進一步學習,你可以通過閱讀 在 Node.js 中建立 GraphQL API 服務器的方法 教程,瞭解創建和修改 GraphQL 模式的實踐,以建立一個可運行的 GraphQL 服務器環境。
Source:
https://www.digitalocean.com/community/conceptual-articles/understanding-the-graphql-type-system