레슨 25: 외부 API의 데이터 변환하기
이 튜토리얼 레슨에서는 외부 API의 응답을 필요한 형태로 변환하는 예시를 소개합니다.
각 항목에 기본값과 추가 속성 부여하기
REST API 엔드포인트 newapi.getpop.org/wp-json/wp/v2/users/?_fields=id,name,url은 사용자 데이터를 반환하지만, 일부 사용자의 url 속성이 비어 있습니다.
[
{
"id": 1,
"name": "leo",
"url": "https://leoloso.com"
},
{
"id": 7,
"name": "Test",
"url": ""
},
{
"id": 2,
"name": "Theme Demos",
"url": ""
}
]아래 GraphQL 쿼리는 이 응답을 변환합니다.
url속성이 비어 있는 사용자에게 기본 URL을 추가합니다.- 각 사용자 항목에
link속성을 추가합니다 (사용자의 이름과 URL 값을 사용하여 구성).
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
)
}응답은 다음과 같습니다.
{
"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>"
}
]
}
}컴포저블 디렉티브는 하나 이상의 디렉티브를 중첩할 수 있습니다. 여러 디렉티브를 중첩할 때는 인수 affectDirectivesUnderPos를 사용하여 지정합니다. 이 인수에는 해당 디렉티브에서 중첩된 디렉티브까지의 상대 위치가 포함됩니다.
위의 GraphQL 쿼리에서 디렉티브 @underEachArrayItem(Field Value Iteration and Manipulation 확장이 제공)은 컴포저블 디렉티브입니다. 첫 번째 사용 시에는 하나의 디렉티브만 중첩하므로 인수 affectDirectivesUnderPos를 생략할 수 있습니다.
@underEachArrayItem
@underJSONObjectProperty(
# ...
)(참고로, @underJSONObjectProperty도 컴포저블 디렉티브로서 @default 디렉티브를 중첩합니다.)
두 번째 사용 시에는 인수 affectDirectivesUnderPos에 값 [1, 2, 3, 4]를 지정하여 오른쪽에 있는 4개의 디렉티브를 중첩합니다.
@underEachArrayItem(
affectDirectivesUnderPos: [1, 2, 3, 4],
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_objectProperty",
# ...
)
@applyField(
name: "_sprintf",
# ...
)
@applyField(
name: "_objectAddEntry",
# ...
)🔥 팁:
디렉티브 @applyField(Field on Field 확장이 제공)에는 출력을 보낼 수 있는 두 가지 대상이 있습니다.
- 인수
passOnwardsAs: "someVariableName"를 지정하면 새 값이 동적 변수$someVariableName에 할당되어 이후 중첩된 디렉티브에서 참조할 수 있습니다.
@applyField(
name: "_objectProperty",
arguments: {
object: $userListItem,
by: {
key: "name"
}
},
passOnwardsAs: "userName"
)- 인수
setResultInResponse: true를 지정하면 새 값이 필드에 다시 할당되어 응답이 수정됩니다.
@applyField(
name: "_objectAddEntry",
arguments: {
object: $userListItem,
key: "link",
value: $userLink
},
setResultInResponse: true
)JSON 객체에서 특정 속성 추출하기
REST API 엔드포인트 newapi.getpop.org/wp-json/newsletter/v1/subscriptions는 구독자의 이메일 주소와 언어를 포함한 이메일 구독 데이터 컬렉션을 반환합니다.
[
{
"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 쿼리는 각 항목에서 email 속성을 추출하여 필드 값으로 대체함으로써 API 응답에서 이메일 주소만 출력합니다.
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
)
}응답은 다음과 같습니다.
{
"data": {
"emails": [
"abracadabra@ganga.com",
"longon@caramanon.com",
"rancotanto@parabara.com",
"quezarapadon@quebrulacha.net",
"test@test.com",
"emilanga@pedrola.com"
]
}
}조건에 따라 필드 값 수정하기
이 예시는 이전 예시를 이어받아 응답의 이메일 주소 형식도 변환합니다.
아래 GraphQL 쿼리는 API 응답에서 이메일 주소를 추출하고, 컴포저블 디렉티브 @if(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
}응답은 다음과 같습니다.
{
"data": {
"emails": [
"ABRACADABRA@GANGA.COM",
"longon@caramanon.com",
"RANCOTANTO@PARABARA.COM",
"quezarapadon@quebrulacha.net",
"TEST@TEST.COM",
"emilanga@pedrola.com"
]
}
}Gato GraphQL에서 조건 로직의 실행은 동적으로 만들 수 있습니다. 쿼리 대상 객체에서 평가된 동적 변수를 @if(condition:)(및 @unless(condition:))에 전달하면 해당 엔티티의 조건에 따라 로직의 실행 여부가 결정됩니다.
이를 통해 다음과 같은 조건을 기반으로 일부 엔티티에 대해서만 동적으로 응답을 수정할 수 있습니다.
- 게시물에 댓글이 있는가?
- 댓글에 답글이 있는가?
- 사용자가 관리자인가?
- 태그/카테고리가 어떤 게시물에 적용되어 있는가?
- 기타