Schema-Tutorial
Schema-TutorialLektion 25: Daten einer externen API transformieren

Lektion 25: Daten einer externen API transformieren

Diese Tutorial-Lektion zeigt Beispiele zur Anpassung der Antwort einer externen API an beliebige Formate.

Standardwerte und zusĂ€tzliche Eigenschaften zu jedem Eintrag hinzufĂŒgen

Der REST-API-Endpunkt newapi.getpop.org/wp-json/wp/v2/users/?_fields=id,name,url liefert Benutzerdaten, wobei einige Benutzer die Eigenschaft url leer haben:

[
  {
    "id": 1,
    "name": "leo",
    "url": "https://leoloso.com"
  },
  {
    "id": 7,
    "name": "Test",
    "url": ""
  },
  {
    "id": 2,
    "name": "Theme Demos",
    "url": ""
  }
]

Die folgende GraphQL-Query transformiert diese Antwort:

  • Indem ein Standard-URL fĂŒr Benutzer hinzugefĂŒgt wird, deren Eigenschaft url leer ist
  • Indem jedem Benutzereintrag eine Eigenschaft link hinzugefĂŒgt wird (zusammengesetzt aus dem Namen und der URL des Benutzers)
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
      )
}

Die Antwort lautet:

{
  "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>"
      }
    ]
  }
}

KompositionsfĂ€hige Direktiven können eine oder mehrere Direktiven in sich verschachteln. Wenn mehr als eine verschachtelt wird, wird dies ĂŒber das Argument affectDirectivesUnderPos angegeben, das die relativen Positionen von dieser Direktive zu ihren verschachtelten Direktiven enthĂ€lt.

In der obigen GraphQL-Query ist die Direktive @underEachArrayItem (bereitgestellt von der Erweiterung Field Value Iteration and Manipulation) eine kompositionsfÀhige Direktive. Bei ihrem ersten Vorkommen verschachtelt sie nur eine Direktive, und das Argument affectDirectivesUnderPos kann weggelassen werden:

    @underEachArrayItem
      @underJSONObjectProperty(
        # ...
      )

(Übrigens: Beachte, dass @underJSONObjectProperty ebenfalls eine kompositionsfĂ€hige Direktive ist, die die Direktive @default verschachtelt.)

Bei ihrem zweiten Vorkommen verschachtelt sie die 4 Direktiven zu ihrer Rechten, wie durch das Argument affectDirectivesUnderPos mit dem Wert [1, 2, 3, 4] angegeben:

    @underEachArrayItem(
      affectDirectivesUnderPos: [1, 2, 3, 4],
      # ...
    )
      @applyField(
        name: "_objectProperty",
        # ...
      )
      @applyField(
        name: "_objectProperty",
        # ...
      )
      @applyField(
        name: "_sprintf",
       # ...
      )
      @applyField(
        name: "_objectAddEntry",
        # ...
      )



đŸ”„ Tipps:

Die Direktive @applyField (bereitgestellt von der Erweiterung Field on Field) hat zwei mögliche Ziele fĂŒr ihre Ausgabe:

  • Das Argument passOnwardsAs: "someVariableName" weist den neuen Wert der dynamischen Variable $someVariableName zu, von der er von den nachfolgenden verschachtelten Direktiven gelesen werden kann:
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $userListItem,
          by: {
            key: "name"
          }
        },
        passOnwardsAs: "userName"
      )
  • Das Argument setResultInResponse: true weist den neuen Wert wieder dem Feld zu (und modifiziert damit die Antwort):
      @applyField(
        name: "_objectAddEntry",
        arguments: {
          object: $userListItem,
          key: "link",
          value: $userLink
        },
        setResultInResponse: true
      )

Eine bestimmte Eigenschaft aus den JSON-Objekten extrahieren

Der REST-API-Endpunkt newapi.getpop.org/wp-json/newsletter/v1/subscriptions liefert eine Sammlung von E-Mail-Abonnementdaten, einschließlich der E-Mail-Adresse und der Sprache des Abonnenten:

[
  {
    "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"
  }
]

Diese GraphQL-Query gibt nur die E-Mail-Adressen aus der API-Antwort aus, indem sie die Eigenschaft email aus jedem Eintrag extrahiert und den Feldwert damit ersetzt:

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
      )
}

Die Antwort lautet:

{
  "data": {
    "emails": [
      "abracadabra@ganga.com",
      "longon@caramanon.com",
      "rancotanto@parabara.com",
      "quezarapadon@quebrulacha.net",
      "test@test.com",
      "emilanga@pedrola.com"
    ]
  }
}

Feldwerte bedingt Àndern

Dieses Beispiel baut auf dem vorherigen auf und konvertiert zusÀtzlich das Format der E-Mail-Adressen in der Antwort.

Die folgende GraphQL-Query extrahiert die E-Mail-Adressen aus der API-Antwort und konvertiert jene von Benutzern, deren Sprache Englisch oder Deutsch ist, in Großbuchstaben – mithilfe der kompositionsfĂ€higen Direktive @if (bereitgestellt von der Erweiterung 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
}

Die Antwort lautet:

{
  "data": {
    "emails": [
      "ABRACADABRA@GANGA.COM",
      "longon@caramanon.com",
      "RANCOTANTO@PARABARA.COM",
      "quezarapadon@quebrulacha.net",
      "TEST@TEST.COM",
      "emilanga@pedrola.com"
    ]
  }
}

Die AusfĂŒhrung bedingter Logik in Gato GraphQL kann dynamisch gestaltet werden: Indem eine dynamische Variable an @if(condition:) (und auch an @unless(condition:)) ĂŒbergeben wird, die am abgefragten Objekt ausgewertet wurde, wird die Logik je nach den Bedingungen dieser EntitĂ€t ausgefĂŒhrt oder nicht.

Auf diese Weise können wir die Antwort fĂŒr bestimmte EntitĂ€ten (und nicht fĂŒr andere) dynamisch Ă€ndern, basierend auf Bedingungen wie:

  • Hat der Beitrag Kommentare?
  • Hat der Kommentar Antworten?
  • Ist der Benutzer ein Administrator?
  • Ist das Tag/die Kategorie einem Beitrag zugewiesen?
  • Usw.