Field Value Iteration and Manipulation

“Personal”
1 domain
“Professional”
5 domains
“Agency”
25 domains

$24.99

$49.99

$99.99

Buying the extension gives you a license for 1 year (renewable every year), that includes support and access to all extension updates. Prices are in USD.

🛍️ Buy “Field Value Iteration and Manipulation” Extension


Addition of meta directives to the GraphQL schema, for iterating and manipulating the value elements of array and object fields:

  1. @underArrayItem
  2. @underJSONObjectProperty
  3. @underEachArrayItem
  4. @underEachJSONObjectProperty
  5. @objectClone

@underArrayItem permalink

@underArrayItem makes the nested directive be applied on a specific item from the array.

In the query below, only the first item in the array with the category names is transformed to uppercase:

query {
posts {
categoryNames
@underArrayItem(index: 0)
@strUpperCase
}
}

...producing:

{
"data": {
"posts": {
"categoryNames": [
"NEWS",
"sports"
]
}
}
}

@underJSONObjectProperty permalink

@underJSONObjectProperty makes the nested directive receive an entry from the queried JSON object.

This directive is particularly useful to extract and manipulate a desired piece of data after querying an external API, which will quite likely have a generic JSONObject type (as when using function field _sendJSONObjectItemHTTPRequest from the HTTP Client extension).

In the query below, we obtain a JSON object coming from the WP REST API, and we use @underJSONObjectProperty to manipulate the response's type property, transforming it to upper case:

query {
postData: _sendJSONObjectItemHTTPRequest(
url: "https://newapi.getpop.org/wp-json/wp/v2/posts/1/?_fields=id,type,title,date"
)
@underJSONObjectProperty(by: { key: "type" })
@strUpperCase
}

This will produce:

{
"data": {
"postData": {
"id": 1,
"date": "2019-08-02T07:53:57",
"type": "POST",
"title": {
"rendered": "Hello world!"
}
}
}
}

In addition to receiving a "key" to point to a property that lives on the first level of the JSON object, this directive can also receive a "path" to navigate within the inner structure of the object, using . as a separator across levels.

In the query below, the WP REST API endpoint for a post provides property "title.rendered". We can navigate to that actual subelement, and transform it to title case:

query {
postData: _sendJSONObjectItemHTTPRequest(
url: "https://newapi.getpop.org/wp-json/wp/v2/posts/1/?_fields=id,type,title,date"
)
@underJSONObjectProperty(by: { path: "title.rendered" })
@strTitleCase
}

This will produce:

{
"data": {
"postData": {
"id": 1,
"date": "2019-08-02T07:53:57",
"type": "post",
"title": {
"rendered": "HELLO WORLD!"
}
}
}
}

@underEachArrayItem permalink

@underEachArrayItem iterates over the array items from some field in the queried entity, and executes the nested directive(s) on each of them.

For instance, field Post.categoryNames is of type [String]. Using @underEachArrayItem, we can iterate the category names and apply the @strTranslate directive to them.

In this query, the post categories are translated from English to French:

query {
posts {
id
title
categoryNames
@underEachArrayItem
@strTranslate(
from: "en",
to: "fr"
)
}
}

...producing:

{
"data": {
"posts": [
{
"id": 662,
"title": "Explaining the privacy policy",
"categoryNames": [
"Non classé"
]
},
{
"id": 28,
"title": "HTTP caching improves performance",
"categoryNames": [
"Avancé"
]
},
{
"id": 25,
"title": "Public or Private API mode, for extra security",
"categoryNames": [
"Ressource",
"Blog",
"Avancé"
]
}
]
}
}

@underEachJSONObjectProperty permalink

@underEachJSONObjectProperty is similar to @underEachArrayItem, but operating on JSONObject elements.

In this query, we iterate all entries in the JSON object and replace any null entry with an empty string:

{
_echo(
value: {
first: "hello",
second: "world",
third: null
}
)
@underEachJSONObjectProperty
@default(value: "")
}

...producing:

{
"data": {
"_echo": {
"first": "hello",
"second": "world",
"third": ""
}
}
}

@objectClone permalink

JSON objects may be accessed by reference in the field resolvers (and not by copying/duplicating the object). When that is the case, when the JSON object is modified, this modification will be visible to all the fields that retrieve this JSON object.

This is the case with field Block.attributes:

{
posts {
blocks(filterBy: { include: "core/heading" } ) {
attributes
}
}
}

...which produces:

{
"data": {
"posts": [
{
"blocks": [
{
"attributes": {
"content": "Image Block (Full width)",
"level": 2
}
},
{
"attributes": {
"content": "Gallery Block",
"level": 2
}
}
]
}
]
}
}

In the query below, while originalAttributes is simply retrieving the attributes, transformedAttributes will also translate the content property to French:

{
posts {
blocks(filterBy: { include: "core/heading" } ) {
originalAttributes: attributes
transformedAttributes: attributes
@underJSONObjectProperty(by: { key: "content" })
@strTranslate(to: "fr")
}
}
}

However, as the queried Block entity references the same JSON object on both originalAttributes and transformedAttributes, the transformations performed by the latter field will also affect the former field (this is irrespective of the order in which they appear in the query).

As a result, both fields are translated to French:

{
"data": {
"posts": [
{
"blocks": [
{
"originalAttributes": {
"content": "Bloc d'image (pleine largeur)",
"level": 2
},
"transformedAttributes": {
"content": "Bloc d'image (pleine largeur)",
"level": 2
}
},
{
"originalAttributes": {
"content": "Bloc Galerie",
"level": 2
},
"transformedAttributes": {
"content": "Bloc Galerie",
"level": 2
}
}
]
}
]
}
}

We can avoid this issue by adding directive @objectClone on the transformedAttributes field, so that the modifications are performed on a cloned JSON object:

{
posts {
blocks(filterBy: { include: "core/heading" } ) {
originalAttributes: attributes
transformedAttributes: attributes
@objectClone
@underJSONObjectProperty(by: { key: "content" })
@strTranslate(to: "fr")
}
}
}

...producing:

{
"data": {
"posts": [
{
"blocks": [
{
"originalAttributes": {
"content": "Image Block (Full width)",
"level": 2
},
"transformedAttributes": {
"content": "Bloc d'image (pleine largeur)",
"level": 2
}
},
{
"originalAttributes": {
"content": "Gallery Block",
"level": 2
},
"transformedAttributes": {
"content": "Bloc Galerie",
"level": 2
}
}
]
}
]
}
}

Further examples permalink

In this query, @underEachArrayItem wraps @underJSONObjectProperty, which itself wraps @strUpperCase, transforming the "title.rendered" property into upper case, for the multiple post entries obtained via the WP REST API:

query {
postListData: _sendJSONObjectCollectionHTTPRequest(
url: "https://newapi.getpop.org/wp-json/wp/v2/posts/?per_page=3&_fields=id,type,title,date"
)
@underEachArrayItem
@underJSONObjectProperty(by: { path: "title.rendered" })
@strUpperCase
}

...producing:

{
"data": {
"postListData": [
{
"id": 1692,
"date": "2022-04-26T10:10:08",
"type": "post",
"title": {
"rendered": "MY BLOGROLL"
}
},
{
"id": 1657,
"date": "2020-12-21T08:24:18",
"type": "post",
"title": {
"rendered": "A TALE OF TWO CITIES – TEASER"
}
},
{
"id": 1499,
"date": "2019-08-08T02:49:36",
"type": "post",
"title": {
"rendered": "COPE WITH WORDPRESS: POST DEMO CONTAINING PLENTY OF BLOCKS"
}
}
]
}
}

Bundles including extension permalink

Recipes using extension permalink


🛍️ Buy “Field Value Iteration and Manipulation” Extension