Lekcja 25: Transformowanie danych z zewnętrznego API
Ta lekcja samouczka demonstruje przykłady adaptowania odpowiedzi z zewnętrznego API do dowolnego wymaganego formatu.
Dodawanie wartości domyślnych i dodatkowych właściwości do każdego wpisu
Endpoint REST API newapi.getpop.org/wp-json/wp/v2/users/?_fields=id,name,url zwraca dane użytkowników, przy czym niektórzy użytkownicy mają pustą właściwość url:
[
{
"id": 1,
"name": "leo",
"url": "https://leoloso.com"
},
{
"id": 7,
"name": "Test",
"url": ""
},
{
"id": 2,
"name": "Theme Demos",
"url": ""
}
]Poniższe query GraphQL transformuje tę odpowiedź:
- Dodając domyślny URL dla użytkowników, których właściwość
urljest pusta - Dodając właściwość
linkdo każdego wpisu użytkownika (złożoną z nazwy i adresu URL użytkownika)
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
)
}Odpowiedź to:
{
"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>"
}
]
}
}Dyrektywy kompozytowe mogą zagnieżdżać w sobie jedną lub więcej dyrektyw. Gdy zagnieżdżamy więcej niż jedną, wskazujemy to za pomocą argumentu affectDirectivesUnderPos, który zawiera względne pozycje od tej dyrektywy do jej zagnieżdżonych dyrektyw.
W powyższym query GraphQL dyrektywa @underEachArrayItem (dostarczana przez rozszerzenie Iteracja i Manipulacja Wartością Pola) jest dyrektywą kompozytową. Przy pierwszym wystąpieniu zagnieżdża tylko jedną dyrektywę i argument affectDirectivesUnderPos może zostać pominięty:
@underEachArrayItem
@underJSONObjectProperty(
# ...
)(Nawiasem mówiąc, zauważ, że @underJSONObjectProperty również jest dyrektywą kompozytową, zagnieżdżającą dyrektywę @default).
Przy drugim wystąpieniu zagnieżdża 4 dyrektywy po swojej prawej stronie, co jest wskazane przez argument affectDirectivesUnderPos z wartością [1, 2, 3, 4]:
@underEachArrayItem(
affectDirectivesUnderPos: [1, 2, 3, 4],
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_sprintf",
# ...
)
@applyField(
name: "_objectAddEntry",
# ...
)🔥 Wskazówki:
Dyrektywa @applyField (dostarczana przez rozszerzenie Pole na Polu) ma dwa potencjalne miejsca docelowe dla swojego wyjścia:
- Podanie argumentu
passOnwardsAs: "someVariableName"przypisze nową wartość do zmiennej dynamicznej$someVariableName, z której będą mogły ją odczytać kolejne zagnieżdżone dyrektywy:
@applyField(
name: "_objectProperty",
arguments: {
object: $userListItem,
by: {
key: "name"
}
},
passOnwardsAs: "userName"
)- Podanie argumentu
setResultInResponse: trueprzypisze nową wartość z powrotem do pola (modyfikując tym samym odpowiedź):
@applyField(
name: "_objectAddEntry",
arguments: {
object: $userListItem,
key: "link",
value: $userLink
},
setResultInResponse: true
)Wyodrębnianie konkretnej właściwości z obiektów JSON
Endpoint REST API newapi.getpop.org/wp-json/newsletter/v1/subscriptions zwraca kolekcję danych subskrypcji e-mail, zawierającą adres e-mail i język subskrybenta:
[
{
"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"
}
]To query GraphQL wyświetla tylko adresy e-mail z odpowiedzi API, wyodrębniając właściwość email z każdego wpisu i zastępując nią wartość pola:
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
)
}Odpowiedź to:
{
"data": {
"emails": [
"abracadabra@ganga.com",
"longon@caramanon.com",
"rancotanto@parabara.com",
"quezarapadon@quebrulacha.net",
"test@test.com",
"emilanga@pedrola.com"
]
}
}Warunkowe modyfikowanie wartości pól
Ten przykład jest kontynuacją poprzedniego i dodatkowo konwertuje format adresów e-mail w odpowiedzi.
Poniższe query GraphQL wyodrębnia adresy e-mail z odpowiedzi API i konwertuje na wielkie litery te należące do użytkowników, których język to angielski lub niemiecki, za pomocą dyrektywy kompozytowej @if (dostarczanej przez rozszerzenie Warunkowa Manipulacja Polem):
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
}Odpowiedź to:
{
"data": {
"emails": [
"ABRACADABRA@GANGA.COM",
"longon@caramanon.com",
"RANCOTANTO@PARABARA.COM",
"quezarapadon@quebrulacha.net",
"TEST@TEST.COM",
"emilanga@pedrola.com"
]
}
}Wykonywanie logiki warunkowej w Gato GraphQL może być dynamiczne: przekazując zmienną dynamiczną do @if(condition:) (a także do @unless(condition:)), która została oceniona na zapytanym obiekcie, logika będzie wykonywana lub nie w zależności od warunków tej encji.
W ten sposób możemy dynamicznie modyfikować odpowiedź dla niektórych encji (a nie dla innych), na podstawie warunków takich jak:
- Czy post ma komentarze?
- Czy komentarz ma odpowiedzi?
- Czy użytkownik jest administratorem?
- Czy tag/kategoria jest przypisana do jakiegoś posta?
- Itd.