Bài 25: Biến đổi dữ liệu từ API bên ngoài
Bài học hướng dẫn này trình bày các ví dụ về cách điều chỉnh phản hồi từ một API bên ngoài thành bất kỳ định dạng nào chúng ta cần.
Thêm giá trị mặc định và thuộc tính bổ sung vào mỗi mục
Endpoint REST API newapi.getpop.org/wp-json/wp/v2/users/?_fields=id,name,url trả về dữ liệu người dùng, trong đó một số người dùng có thuộc tính url trống:
[
{
"id": 1,
"name": "leo",
"url": "https://leoloso.com"
},
{
"id": 7,
"name": "Test",
"url": ""
},
{
"id": 2,
"name": "Theme Demos",
"url": ""
}
]GraphQL query bên dưới biến đổi phản hồi này:
- Thêm URL mặc định cho những người dùng có thuộc tính
urltrống - Thêm thuộc tính
linkvào mỗi mục người dùng (được tạo thành từ tên và URL của người dùng)
query {
# Retrieve data from the external API
usersWithLinkAndDefaultURL: _sendJSONObjectCollectionHTTPRequest(
input: {
url: "https://newapi.getpop.org/wp-json/wp/v2/users/?_fields=id,name,url"
}
)
# Set a default URL for users without any
@underEachArrayItem
@underJSONObjectProperty(
by: {
key: "url"
}
)
@default(
value: "https://mysite.com"
condition: IS_EMPTY
)
# Add a new "link" entry on the JSON object
@underEachArrayItem(
affectDirectivesUnderPos: [1, 2, 3, 4],
passValueOnwardsAs: "userListItem"
)
@applyField(
name: "_objectProperty",
arguments: {
object: $userListItem,
by: {
key: "name"
}
},
passOnwardsAs: "userName"
)
@applyField(
name: "_objectProperty",
arguments: {
object: $userListItem,
by: {
key: "url"
}
},
passOnwardsAs: "userURL"
)
@applyField(
name: "_sprintf",
arguments: {
string: "<a href=\"%s\">%s</a>",
values: [$userURL, $userName]
},
passOnwardsAs: "userLink"
)
@applyField(
name: "_objectAddEntry",
arguments: {
object: $userListItem,
key: "link",
value: $userLink
},
setResultInResponse: true
)
}Phản hồi là:
{
"data": {
"usersWithLinkAndDefaultURL": [
{
"id": 1,
"name": "leo",
"url": "https://leoloso.com",
"link": "<a href=\"https://leoloso.com\">leo</a>"
},
{
"id": 7,
"name": "Test",
"url": "https://mysite.com",
"link": "<a href=\"https://mysite.com\">Test</a>"
},
{
"id": 2,
"name": "Theme Demos",
"url": "https://mysite.com",
"link": "<a href=\"https://mysite.com\">Theme Demos</a>"
}
]
}
}Các directive có thể kết hợp có thể lồng một hoặc nhiều directive bên trong chúng. Khi lồng nhiều hơn một, chúng ta chỉ định điều này thông qua tham số affectDirectivesUnderPos, chứa các vị trí tương đối từ directive đó đến các directive lồng nhau của nó.
Trong GraphQL query ở trên, directive @underEachArrayItem (được cung cấp bởi extension Field Value Iteration and Manipulation) là một directive có thể kết hợp. Ở lần xuất hiện đầu tiên, nó chỉ lồng một directive, và tham số affectDirectivesUnderPos có thể được bỏ qua:
@underEachArrayItem
@underJSONObjectProperty(
# ...
)(Nhân tiện, lưu ý rằng @underJSONObjectProperty cũng là một directive có thể kết hợp, lồng directive @default).
Ở lần xuất hiện thứ hai, nó lồng 4 directive ở bên phải của nó, như được chỉ định bởi tham số affectDirectivesUnderPos với giá trị [1, 2, 3, 4]:
@underEachArrayItem(
affectDirectivesUnderPos: [1, 2, 3, 4],
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_sprintf",
# ...
)
@applyField(
name: "_objectAddEntry",
# ...
)🔥 Mẹo:
Directive @applyField (được cung cấp bởi extension Field on Field) có hai đích đến tiềm năng cho đầu ra của nó:
- Cung cấp tham số
passOnwardsAs: "someVariableName"sẽ gán giá trị mới cho biến động$someVariableName, từ đó có thể được đọc bởi các directive lồng nhau tiếp theo:
@applyField(
name: "_objectProperty",
arguments: {
object: $userListItem,
by: {
key: "name"
}
},
passOnwardsAs: "userName"
)- Cung cấp tham số
setResultInResponse: truesẽ gán giá trị mới trở lại cho field (do đó nó sẽ sửa đổi phản hồi):
@applyField(
name: "_objectAddEntry",
arguments: {
object: $userListItem,
key: "link",
value: $userLink
},
setResultInResponse: true
)Trích xuất một thuộc tính cụ thể từ các đối tượng JSON
Endpoint REST API newapi.getpop.org/wp-json/newsletter/v1/subscriptions trả về một tập hợp dữ liệu đăng ký email, bao gồm email và ngôn ngữ của người đăng ký:
[
{
"email": "abracadabra@ganga.com",
"lang": "de"
},
{
"email": "longon@caramanon.com",
"lang": "es"
},
{
"email": "rancotanto@parabara.com",
"lang": "en"
},
{
"email": "quezarapadon@quebrulacha.net",
"lang": "fr"
},
{
"email": "test@test.com",
"lang": "de"
},
{
"email": "emilanga@pedrola.com",
"lang": "fr"
}
]GraphQL query này chỉ in ra các email từ phản hồi API, bằng cách trích xuất thuộc tính email từ mỗi mục và thay thế giá trị field bằng nó:
query {
emails: _sendJSONObjectCollectionHTTPRequest(
input: {
url: "https://newapi.getpop.org/wp-json/newsletter/v1/subscriptions"
}
)
@underEachArrayItem(
passValueOnwardsAs: "userEntry"
)
@applyField(
name: "_objectProperty"
arguments: {
object: $userEntry,
by: {
key: "email"
}
}
setResultInResponse: true
)
}Phản hồi là:
{
"data": {
"emails": [
"abracadabra@ganga.com",
"longon@caramanon.com",
"rancotanto@parabara.com",
"quezarapadon@quebrulacha.net",
"test@test.com",
"emilanga@pedrola.com"
]
}
}Sửa đổi giá trị field theo điều kiện
Ví dụ này tiếp nối ví dụ trước, đồng thời cũng chuyển đổi định dạng của các email trong phản hồi.
GraphQL query bên dưới trích xuất các email từ phản hồi của API, và chuyển đổi thành chữ hoa những email của người dùng có ngôn ngữ là tiếng Anh hoặc tiếng Đức thông qua directive có thể kết hợp @if (được cung cấp bởi extension Conditional Field Manipulation):
query {
# Retrieve data from a REST API endpoint
userEntries: _sendJSONObjectCollectionHTTPRequest(
input: {
url: "https://newapi.getpop.org/wp-json/newsletter/v1/subscriptions"
}
)
@remove
emails: _echo(value: $__userEntries)
# Iterate all the entries, passing every entry
# (under the dynamic variable $userEntry)
# to each of the next 4 directives
@underEachArrayItem(
passValueOnwardsAs: "userEntry"
affectDirectivesUnderPos: [1, 2, 3, 4]
)
# Extract property "lang" from the entry
# via the functionality field `_objectProperty`,
# and pass it onwards as dynamic variable $userLang
@applyField(
name: "_objectProperty"
arguments: {
object: $userEntry,
by: {
key: "lang"
}
}
passOnwardsAs: "userLang"
)
# Execute functionality field `_inArray` to find out
# if $userLang is either "en" or "de", and place the
# result under dynamic variable $isSpecialLang
@applyField(
name: "_inArray"
arguments: {
value: $userLang,
array: ["en", "de"]
}
passOnwardsAs: "isSpecialLang"
)
# Extract property "email" from the entry
# and set it back as the value for that entry
@applyField(
name: "_objectProperty"
arguments: {
object: $userEntry,
by: {
key: "email"
}
}
setResultInResponse: true
)
# If $isSpecialLang is `true` then execute
# directive `@strUpperCase`
@if(condition: $isSpecialLang)
@strUpperCase
}Phản hồi là:
{
"data": {
"emails": [
"ABRACADABRA@GANGA.COM",
"longon@caramanon.com",
"RANCOTANTO@PARABARA.COM",
"quezarapadon@quebrulacha.net",
"TEST@TEST.COM",
"emilanga@pedrola.com"
]
}
}Việc thực thi logic có điều kiện trong Gato GraphQL có thể được thực hiện động: Bằng cách truyền một biến động vào @if(condition:) (và cả @unless(condition:)) đã được đánh giá trên đối tượng được truy vấn, logic sẽ được thực thi hay không tùy thuộc vào các điều kiện từ thực thể đó.
Theo cách này, chúng ta có thể sửa đổi động phản hồi cho một số thực thể (và không phải cho các thực thể khác), dựa trên các điều kiện như:
- Bài viết có bình luận không?
- Bình luận có phản hồi không?
- Người dùng có phải là quản trị viên không?
- Tag/danh mục có được áp dụng cho một số bài viết không?
- Vv.