Guide de programmation du modèle de mappage des résolveurs - AWS AppSync

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Guide de programmation du modèle de mappage des résolveurs

Il s'agit d'un tutoriel de type livre de recettes sur la programmation en langage Apache VTL (Velocity Template Language) dans AWS AppSync. Si vous connaissez d'autres langages de programmation tels que JavaScript C ou Java, cela devrait être assez simple.

AWS AppSync utilise VTL pour traduire les requêtes GraphQL des clients en une demande adressée à votre source de données. Ensuite, il inverse ce processus pour convertir la réponse de la source de données en une réponse GraphQL. VTL est un langage de modèle logique qui vous permet de manipuler à la fois la demande et la réponse dans le flux standard de requêtes/réponses d'une application Web, en utilisant des techniques telles que :

  • Valeurs par défaut pour les nouveaux éléments

  • Validation et formatage des informations fournies

  • Transformation et mise en forme des données

  • Itération sur des listes, des cartes et des tableaux pour manipuler ou modifier les valeurs

  • Filtrage/modification des réponses en fonction de l'identité de l'utilisateur

  • Vérifications d'autorisation complexes

Par exemple, vous souhaiterez peut-être valider un numéro de téléphone dans le service sur un argument GraphQL, ou convertir un paramètre d'entrée en majuscules avant de le stocker dans DynamoDB. Les systèmes clients peuvent également fournir un code, dans le cadre d'un argument GraphQL, d'une demande de jeton JWT ou d'un en-tête HTTP, et ne répondre avec des données que si ce code correspond à une chaîne spécifique dans une liste. Ce sont toutes des vérifications logiques que vous pouvez effectuer avec VTL intégréAWS AppSync.

VTL permet d'appliquer une logique à l'aide de techniques de programmation qui peuvent vous être familières. Toutefois, son exécution est limitée au flux de demande/réponse standard pour garantir que votre API GraphQL est scalable lorsque votre base d'utilisateurs croît. Comme il estAWS AppSync également compatible enAWS Lambda tant que résolveur, vous pouvez écrire des fonctions Lambda dans le langage de programmation de votre choix (Node.js, Python, Go, Java, etc.) si vous avez besoin de plus de flexibilité.

Installation

Une technique courante lors de l'apprentissage d'une langue consiste à imprimer les résultats (par exemple,console.log(variable) dans JavaScript) pour voir ce qui se passe. Dans ce didacticiel, nous illustrons cela en créant un schéma GraphQL simple et en transmettant une carte de valeurs à une fonction Lambda. La fonction Lambda affiche les valeurs, puis les utilise pour répondre. Ceci vous permet de comprendre le flux de demande/réponse et de voir différentes techniques de programmation.

Commencez par créer le schéma GraphQL suivant :

type Query { get(id: ID, meta: String): Thing } type Thing { id: ID! title: String! meta: String } schema { query: Query }

À présent, créez la fonction AWS Lambda suivante, en utilisant Node.js comme langage :

exports.handler = (event, context, callback) => { console.log('VTL details: ', event); callback(null, event); };

Dans le volet Sources de données de la console AWS AppSync , ajoutez cette fonction Lambda en tant que nouvelle source de données. Revenez à la page Schema (Schéma) de la console et cliquez sur le bouton ATTACH (ATTACHER) situé à droite, en regard de la requête get(...):Thing. Pour le modèle de demande, choisissez le modèle existant dans le menu Invoke and forward arguments (Invoquer et transférer des arguments). Pour le modèle de réponse, choisissez Return Lambda result (Renvoyer le résultat de Lambda).

Ouvrez Amazon CloudWatch Logs pour votre fonction Lambda à un seul endroit et, depuis l'onglet Requêtes de laAWS AppSync console, exécutez la requête GraphQL suivante :

query test { get(id:123 meta:"testing"){ id meta } }

La réponse GraphQL doit contenir id:123 et meta:testing, parce que la fonction Lambda en fait écho. Après quelques secondes, vous devriez également voir un enregistrement dans CloudWatch les journaux contenant ces informations.

Variables

VTL utilise des références, que vous pouvez utiliser pour stocker ou manipuler les données. Il existe trois types de références dans VTL : les variables, les propriétés et les méthodes. Les variables sont précédées d'un symbole $ et sont créées avec la directive #set :

#set($var = "a string")

Les variables stockent des types similaires que vous connaissez bien dans d'autres langages, comme des nombres, des chaînes, des tableaux, des listes et des cartes. Vous avez peut-être remarqué qu'une charge utile JSON était envoyée dans le modèle de demande par défaut pour les résolveurs Lambda :

"payload": $util.toJson($context.arguments)

Deux choses sont à noter ici : tout d'abord, AWS AppSync fournit plusieurs fonctions pratiques pour les opérations courantes. Dans cet exemple, $util.toJson convertit une variable au format JSON. Deuxièmement, la variable $context.arguments est automatiquement renseignée à partir d'une demande GraphQL comme un objet carte. Vous pouvez créer une nouvelle carte comme suit :

#set( $myMap = { "id": $context.arguments.id, "meta": "stuff", "upperMeta" : $context.arguments.meta.toUpperCase() } )

Vous venez de créer une variable nommée $myMap, qui possède des clés de id, meta et upperMeta. Ceci illustre aussi les éléments suivants :

  • id est renseignée avec une clé issue des arguments GraphQL. Il est courant dans VTL de saisir des arguments à partir des clients.

  • L'argument meta est codé en dur avec une valeur, exposant les valeurs par défaut.

  • upperMeta transforme l'argument meta à l'aide d'une méthode .toUpperCase().

Placez le code précédent en haut de votre modèle de demande et modifiez payload pour utiliser la nouvelle variable $myMap :

"payload": $util.toJson($myMap)

Exécutez votre fonction Lambda et vous pourrez voir le changement de réponse ainsi que ces données dans CloudWatch les journaux. Au fur et à mesure que vous parcourrez le reste de ce didacticiel, nous continuerons à renseigner $myMap pour que vous puissiez exécuter des tests similaires.

Vous pouvez également définir des propriétés sur vos variables. Ce peut être de simples chaînes, des tableaux ou des éléments JSON :

#set($myMap.myProperty = "ABC") #set($myMap.arrProperty = ["Write", "Some", "GraphQL"]) #set($myMap.jsonProperty = { "AppSync" : "Offline and Realtime", "Cognito" : "AuthN and AuthZ" })

Références silencieuses

Comme VTL est un langage de création de modèles, par défaut, toute référence que vous lui donnez exécute une méthode .toString(). Si la référence n'est pas définie, elle affiche la représentation de référence en tant que chaîne. Par exemple :

#set($myValue = 5) ##Prints '5' $myValue ##Prints '$somethingelse' $somethingelse

Pour résoudre cela, VTL possède une syntaxe de type référence calme ou référence silencieuse, qui indique au moteur de modèle de supprimer ce comportement. La syntaxe correspondante est $!{}. Par exemple, si nous modifions légèrement le code précédent pour utiliser $!{somethingelse}, l'affichage est supprimé :

#set($myValue = 5) ##Prints '5' $myValue ##Nothing prints out $!{somethingelse}

Appel de méthodes

Dans l'exemple précédent, nous vous a montré comment créer une variable et les valeurs définies simultanément. Vous pouvez également procéder en deux étapes en ajoutant des données à votre carte :

#set ($myMap = {}) #set ($myList = []) ##Nothing prints out $!{myMap.put("id", "first value")} ##Prints "first value" $!{myMap.put("id", "another value")} ##Prints true $!{myList.add("something")}

TOUTEFOIS, vous devez connaître une information importante sur ce comportement. Même si la notation de référence silencieuse $!{} vous permet d'appeler des méthodes, comme ci-dessus, elle NE supprime PAS la valeur renvoyée de la méthode exécutée. C'est pourquoi nous avons noté ##Prints "first value" et ##Prints true ci-dessus. Cela peut entraîner des erreurs lors d'une itération sur des cartes ou des listes, comme l'insertion d'une valeur là où une clé existe déjà, car la sortie ajoute des chaînes inattendues au modèle lors de l'évaluation.

Une solution de contournement consiste parfois à appeler les méthodes à l'aide d'une directive #set et d'ignorer la variable. Par exemple :

#set ($myMap = {}) #set($discard = $myMap.put("id", "first value"))

Vous pouvez utiliser cette technique dans vos modèles, car elle empêche l'impression de chaînes inattendues dans le modèle. AWS AppSync fournit une fonction de commodité alternative qui offre le même comportement dans une notation plus succincte. Cela vous évite d'avoir à réfléchir à ces spécificités de mise en œuvre. Vous pouvez accéder à cette fonction sous $util.quiet() ou son alias $util.qr(). Par exemple :

#set ($myMap = {}) #set ($myList = []) ##Nothing prints out $util.quiet($myMap.put("id", "first value")) ##Nothing prints out $util.qr($myList.add("something"))

Chaînes

Comme avec de nombreux langages de programmation, il peut être difficile de gérer les chaînes, notamment lorsque vous voulez les générer à partir de variables. Des éléments communs se manifestent dans le cadre de VTL.

Supposons que vous insériez des données sous forme de chaîne dans une source de données telle que DynamoDB, mais qu'elles soient renseignées à partir d'une variable, comme un argument GraphQL. Une chaîne a des guillemets doubles et vous avez simplement besoin de "${}" pour référencer la variable dans une chaîne (donc d'aucun ! comme dans la notation de référence silencieuse). Cela ressemble à un modèle littéral dans JavaScript : https://developer.mozilla.org/en-US/docs/Web/JavaScript /reference/template_literals

#set($firstname = "Jeff") $!{myMap.put("Firstname", "${firstname}")}

Vous pouvez le constater dans les modèles de requêtes DynamoDB, par exemple"author": { "S" : "${context.arguments.author}"} lorsque vous utilisez des arguments provenant de clients GraphQL, ou pour la génération automatique d'identifiants, par exemple"id" : { "S" : "$util.autoId()"}. Cela signifie que vous pouvez référencer une variable ou le résultat d'une méthode à l'intérieur d'une chaîne pour renseigner les données.

Vous pouvez également utiliser les méthodes publiques de la classe String Java, telles que l'extraction d'une sous-chaîne :

#set($bigstring = "This is a long string, I want to pull out everything after the comma") #set ($comma = $bigstring.indexOf(',')) #set ($comma = $comma +2) #set ($substring = $bigstring.substring($comma)) $util.qr($myMap.put("substring", "${substring}"))

La concaténation de chaînes est aussi une tâche très courante. Vous pouvez procéder avec des références de variables seules ou avec des valeurs statiques :

#set($s1 = "Hello") #set($s2 = " World") $util.qr($myMap.put("concat","$s1$s2")) $util.qr($myMap.put("concat2","Second $s1 World"))

Boucles

Maintenant que vous avez créé des variables et appelé des méthodes, vous pouvez ajouter une logique à votre code. Contrairement à d'autres langages, VTL autorise uniquement des boucles avec un nombre d'itérations prédéterminé. Il n'existe pas de do..while dans Velocity. Cette conception garantit que le processus d'évaluation arrivera à son terme et elle fournit des limites pour la scalabilité lorsque vos opérations GraphQL s'exécutent.

L'instruction #foreach permet de créer des boucles et nécessite que vous fournissiez une variable de boucle et un objet itérable, tel qu'un tableau, une liste, une carte ou une collection. Un exemple de programmation standard avec une boucle #foreach consiste à itérer sur les éléments d'une collection et à les afficher, pour les prélever et les ajouter à la carte :

#set($start = 0) #set($end = 5) #set($range = [$start..$end]) #foreach($i in $range) ##$util.qr($myMap.put($i, "abc")) ##$util.qr($myMap.put($i, $i.toString()+"foo")) ##Concat variable with string $util.qr($myMap.put($i, "${i}foo")) ##Reference a variable in a string with "${varname}" #end

Cet exemple illustre quelques éléments. Le premier est l'utilisation des variables avec l'opérateur [..] de plage pour créer un objet itérable. Ensuite, chaque élément est référencé par une variable $i que vous pouvez utiliser. Dans l'exemple précédent, vous voyez aussi des commentaires qui sont signalés par deux dièses ##. Ceci illustre également l'utilisation de la variable de boucle dans les clés et les valeurs, ainsi que différentes méthodes de concaténation utilisant les chaînes.

Notez que $i est un entier, si bien que vous pouvez appeler une méthode .toString(). Pour les types GraphQL de INT, cela peut être utile.

Vous pouvez également utiliser un opérateur de plage directement, par exemple :

#foreach($item in [1..5]) ... #end

Arrays (tableaux)

Vous avez manipulé une carte jusqu'à ce stade, mais les tableaux sont également courants dans VTL. Avec les tableaux, vous avez également accès à certaines méthodes sous-jacentes telles que .isEmpty(), .size(), .set(), .get() et .add(), comme illustré ci-dessous :

#set($array = []) #set($idx = 0) ##adding elements $util.qr($array.add("element in array")) $util.qr($myMap.put("array", $array[$idx])) ##initialize array vals on create #set($arr2 = [42, "a string", 21, "test"]) $util.qr($myMap.put("arr2", $arr2[$idx])) $util.qr($myMap.put("isEmpty", $array.isEmpty())) ##isEmpty == false $util.qr($myMap.put("size", $array.size())) ##Get and set items in an array $util.qr($myMap.put("set", $array.set(0, 'changing array value'))) $util.qr($myMap.put("get", $array.get(0)))

L'exemple précédent utilisait la notation d'index matriciel pour récupérer un élément avecarr2[$idx]. Vous pouvez rechercher par nom à partir d'une carte/d'un dictionnaire d'une manière similaire :

#set($result = { "Author" : "Nadia", "Topic" : "GraphQL" }) $util.qr($myMap.put("Author", $result["Author"]))

Cela est très courant lors du filtrage des résultats provenant des sources de données dans les modèles de réponse lors de l'utilisation de conditions.

Vérifications conditionnelles

La section antérieure avec #foreach illustrait des exemples de l'utilisation d'une logique pour transformer les données avec VTL. Vous pouvez également appliquer des contrôles conditionnels pour évaluer les données lors de l'exécution :

#if(!$array.isEmpty()) $util.qr($myMap.put("ifCheck", "Array not empty")) #else $util.qr($myMap.put("ifCheck", "Your array is empty")) #end

La vérification #if() ci-dessus d'une expression booléenne est correcte, mais vous pouvez également utiliser des opérateurs et #elseif() pour une ramification :

#if ($arr2.size() == 0) $util.qr($myMap.put("elseIfCheck", "You forgot to put anything into this array!")) #elseif ($arr2.size() == 1) $util.qr($myMap.put("elseIfCheck", "Good start but please add more stuff")) #else $util.qr($myMap.put("elseIfCheck", "Good job!")) #end

Ces deux exemples montrent la négation (!) et l'égalité (==). Nous pouvons également utiliser ||, &&, >, <, >=, <=, et !=

#set($T = true) #set($F = false) #if ($T || $F) $util.qr($myMap.put("OR", "TRUE")) #end #if ($T && $F) $util.qr($myMap.put("AND", "TRUE")) #end

Remarque : Seuls Boolean.FALSE et null sont considérés comme false dans les conditions. Zéro (0) et les chaînes vides ("") ne sont pas équivalents à false.

Opérateurs

Aucun langage de programmation ne serait complet sans certains opérateurs pour effectuer certaines opérations mathématiques. Voici quelques exemples pour commencer :

#set($x = 5) #set($y = 7) #set($z = $x + $y) #set($x-y = $x - $y) #set($xy = $x * $y) #set($xDIVy = $x / $y) #set($xMODy = $x % $y) $util.qr($myMap.put("z", $z)) $util.qr($myMap.put("x-y", $x-y)) $util.qr($myMap.put("x*y", $xy)) $util.qr($myMap.put("x/y", $xDIVy)) $util.qr($myMap.put("x|y", $xMODy))

Association de boucles et de conditions

Il est très courant lors de la transformation de données dans VTL, par exemple avant d'écrire ou de lire dans une source de données, d'itérer sur des objets puis d'effectuer des vérifications avant d'effectuer une action. L'association de certains outils des sections précédentes vous offre un grand nombre de fonctionnalités. Un outil pratique est de savoir que #foreach vous fournit automatiquement un nombre (.count) sur chaque élément :

#foreach ($item in $arr2) #set($idx = "item" + $foreach.count) $util.qr($myMap.put($idx, $item)) #end

Par exemple, vous voulez prélever des valeurs d'une carte seulement si sa taille est inférieure à une valeur donnée. L'utilisation du nombre avec les conditions et l'instruction #break vous permet d'écrire :

#set($hashmap = { "DynamoDB" : "https://aws.amazon.com/dynamodb/", "Amplify" : "https://github.com/aws/aws-amplify", "DynamoDB2" : "https://aws.amazon.com/dynamodb/", "Amplify2" : "https://github.com/aws/aws-amplify" }) #foreach ($key in $hashmap.keySet()) #if($foreach.count > 2) #break #end $util.qr($myMap.put($key, $hashmap.get($key))) #end

Le bloc #foreach précédent est itéré avec .keySet(), que vous pouvez utiliser sur les cartes. Cela vous donne l'accès nécessaire pour obtenir $key et référencer la valeur avec un .get($key). Les arguments GraphQL provenant des clients dans AWS AppSync sont stockés en tant que carte. Ils peuvent également être itérés avec .entrySet() et vous pouvez ensuite accéder à la fois aux clés et aux valeurs en tant qu'ensemble, et renseigner les autres variables ou effectuer des vérifications conditionnelles complexes, telles que la validation ou la transformation de l'entrée :

#foreach( $entry in $context.arguments.entrySet() ) #if ($entry.key == "XYZ" && $entry.value == "BAD") #set($myvar = "...") #else #break #end #end

D'autres exemples courants sont le remplissage automatique des informations par défaut, comme les versions initiales de l'objet lors de la synchronisation des données (très importante pour la résolution de conflits) ou le propriétaire par défaut d'un objet pour les contrôles d'autorisation. Mary a créé ce billet de blog, donc :

#set($myMap.owner ="Mary") #set($myMap.defaultOwners = ["Admins", "Editors"])

Contexte

Maintenant que vous savez comment effectuer des vérifications logiques dansAWS AppSync les résolveurs avec VTL, examinez l'objet contextuel :

$util.qr($myMap.put("context", $context))

Celui-ci contient toutes les informations auxquelles vous pouvez accéder dans votre demande GraphQL. Pour une explication détaillée, consultez la référence sur le contexte.

Filtrage

Jusqu'ici dans ce didacticiel, toutes les informations provenant de votre fonction Lambda ont été renvoyées à la requête GraphQL avec une transformation JSON très simple :

$util.toJson($context.result)

La logique VTL est tout aussi puissante lorsque vous obtenez des réponses à partir d'une source de données, en particulier lors de la réalisation de vérifications d'autorisation sur les ressources. Passons en revue quelques exemples. Tout d'abord, essayez de modifier votre modèle de réponse comme suit :

#set($data = { "id" : "456", "meta" : "Valid Response" }) $util.toJson($data)

Quoi qu'il se passe avec votre opération GraphQL, les valeurs codées en dur sont renvoyées au client. Modifiez cela légèrement pour que le champ meta soit renseigné à partir de la réponse Lambda, définie précédemment dans le didacticiel dans la valeur elseIfCheck lors de l'examen des conditions :

#set($data = { "id" : "456" }) #foreach($item in $context.result.entrySet()) #if($item.key == "elseIfCheck") $util.qr($data.put("meta", $item.value)) #end #end $util.toJson($data)

$context.result est une carte. Vous pouvez donc utiliser entrySet() pour appliquer une logique sur les clés ou les valeurs renvoyées. Etant donné que $context.identity contient des informations sur l'utilisateur qui a effectué l'opération GraphQL, si vous renvoyez les informations d'autorisation à partir de la source de données, vous pouvez décider de renvoyer des données complètes, des données partielles ou aucune donnée à un utilisateur en fonction de votre logique. Modifiez votre modèle de réponse pour qu'il ressemble à ce qui suit :

#if($context.result["id"] == 123) $util.toJson($context.result) #else $util.unauthorized() #end

Si vous exécutez votre requête GraphQL, les données seront renvoyées comme d'habitude. Toutefois, si vous modifiez l'argument id en spécifiant autre chose que 123 (query test { get(id:456 meta:"badrequest"){} }), vous obtenez un message d'échec d'autorisation.

Vous trouverez d'autres exemples de scénarios d'autorisation dans la section sur les cas d'utilisation des autorisations.

Annexe - Exemple de modèle

Si vous avez suivi ce didacticiel, vous avez peut-être créé le modèle ci-dessous étape par étape. Si vous ne l'avez pas fait, nous l'incluons ci-dessous pour que vous puissiez le copier à des fins de test.

Modèle de demande

#set( $myMap = { "id": $context.arguments.id, "meta": "stuff", "upperMeta" : "$context.arguments.meta.toUpperCase()" } ) ##This is how you would do it in two steps with a "quiet reference" and you can use it for invoking methods, such as .put() to add items to a Map #set ($myMap2 = {}) $util.qr($myMap2.put("id", "first value")) ## Properties are created with a dot notation #set($myMap.myProperty = "ABC") #set($myMap.arrProperty = ["Write", "Some", "GraphQL"]) #set($myMap.jsonProperty = { "AppSync" : "Offline and Realtime", "Cognito" : "AuthN and AuthZ" }) ##When you are inside a string and just have ${} without ! it means stuff inside curly braces are a reference #set($firstname = "Jeff") $util.qr($myMap.put("Firstname", "${firstname}")) #set($bigstring = "This is a long string, I want to pull out everything after the comma") #set ($comma = $bigstring.indexOf(',')) #set ($comma = $comma +2) #set ($substring = $bigstring.substring($comma)) $util.qr($myMap.put("substring", "${substring}")) ##Classic for-each loop over N items: #set($start = 0) #set($end = 5) #set($range = [$start..$end]) #foreach($i in $range) ##Can also use range operator directly like #foreach($item in [1...5]) ##$util.qr($myMap.put($i, "abc")) ##$util.qr($myMap.put($i, $i.toString()+"foo")) ##Concat variable with string $util.qr($myMap.put($i, "${i}foo")) ##Reference a variable in a string with "${varname)" #end ##Operators don't work #set($x = 5) #set($y = 7) #set($z = $x + $y) #set($x-y = $x - $y) #set($xy = $x * $y) #set($xDIVy = $x / $y) #set($xMODy = $x % $y) $util.qr($myMap.put("z", $z)) $util.qr($myMap.put("x-y", $x-y)) $util.qr($myMap.put("x*y", $xy)) $util.qr($myMap.put("x/y", $xDIVy)) $util.qr($myMap.put("x|y", $xMODy)) ##arrays #set($array = ["first"]) #set($idx = 0) $util.qr($myMap.put("array", $array[$idx])) ##initialize array vals on create #set($arr2 = [42, "a string", 21, "test"]) $util.qr($myMap.put("arr2", $arr2[$idx])) $util.qr($myMap.put("isEmpty", $array.isEmpty())) ##Returns false $util.qr($myMap.put("size", $array.size())) ##Get and set items in an array $util.qr($myMap.put("set", $array.set(0, 'changing array value'))) $util.qr($myMap.put("get", $array.get(0))) ##Lookup by name from a Map/dictionary in a similar way: #set($result = { "Author" : "Nadia", "Topic" : "GraphQL" }) $util.qr($myMap.put("Author", $result["Author"])) ##Conditional examples #if(!$array.isEmpty()) $util.qr($myMap.put("ifCheck", "Array not empty")) #else $util.qr($myMap.put("ifCheck", "Your array is empty")) #end #if ($arr2.size() == 0) $util.qr($myMap.put("elseIfCheck", "You forgot to put anything into this array!")) #elseif ($arr2.size() == 1) $util.qr($myMap.put("elseIfCheck", "Good start but please add more stuff")) #else $util.qr($myMap.put("elseIfCheck", "Good job!")) #end ##Above showed negation(!) and equality (==), we can also use OR, AND, >, <, >=, <=, and != #set($T = true) #set($F = false) #if ($T || $F) $util.qr($myMap.put("OR", "TRUE")) #end #if ($T && $F) $util.qr($myMap.put("AND", "TRUE")) #end ##Using the foreach loop counter - $foreach.count #foreach ($item in $arr2) #set($idx = "item" + $foreach.count) $util.qr($myMap.put($idx, $item)) #end ##Using a Map and plucking out keys/vals #set($hashmap = { "DynamoDB" : "https://aws.amazon.com/dynamodb/", "Amplify" : "https://github.com/aws/aws-amplify", "DynamoDB2" : "https://aws.amazon.com/dynamodb/", "Amplify2" : "https://github.com/aws/aws-amplify" }) #foreach ($key in $hashmap.keySet()) #if($foreach.count > 2) #break #end $util.qr($myMap.put($key, $hashmap.get($key))) #end ##concatenate strings #set($s1 = "Hello") #set($s2 = " World") $util.qr($myMap.put("concat","$s1$s2")) $util.qr($myMap.put("concat2","Second $s1 World")) $util.qr($myMap.put("context", $context)) { "version" : "2017-02-28", "operation": "Invoke", "payload": $util.toJson($myMap) }

Modèle de réponse

#set($data = { "id" : "456" }) #foreach($item in $context.result.entrySet()) ##$context.result is a MAP so we use entrySet() #if($item.key == "ifCheck") $util.qr($data.put("meta", "$item.value")) #end #end ##Uncomment this out if you want to test and remove the below #if check ##$util.toJson($data) #if($context.result["id"] == 123) $util.toJson($context.result) #else $util.unauthorized() #end