Transformación de datos con JSONata In Step Functions - AWS Step Functions

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Transformación de datos con JSONata In Step Functions

Con JSONata él, obtiene un potente lenguaje de consultas y expresiones de código abierto para seleccionar y transformar los datos en sus flujos de trabajo. Para obtener una breve introducción y una JSONata referencia completa, consulte la documentación de JSONata .org.

En el siguiente vídeo se describen las variables y, JSONata en Step Functions, con un ejemplo de DynamoDB:

Debe optar por utilizar el lenguaje de JSONata consulta y transformación para los flujos de trabajo existentes. Al crear un flujo de trabajo en la consola, le recomendamos que elija la JSONata máquina de estados de nivel superior. QueryLanguage Para los flujos de trabajo nuevos o existentes que se utilicen JSONPath, la consola ofrece una opción para convertir estados individuales en. JSONata

Tras JSONata seleccionarlos, los campos del flujo de trabajo se reducirán de cinco JSONPath campos (InputPathParametersResultSelectorResultPath,, yOutputPath) a solo dos campos: Arguments yOutput. Además, no los utilizarás .$ en JSON nombres clave de objetos.

Si es la primera vez que utiliza Step Functions, solo necesita saber que JSONata las expresiones utilizan la siguiente sintaxis:

JSONata sintaxis: "{% <JSONata expression> %}"

Los siguientes ejemplos de código muestran una conversión de JSONPath a JSONata:

# Original sample using JSONPath { "QueryLanguage": "JSONPath", // Set explicitly; could be set and inherited from top-level "Type": "Task", ... "Parameters": { "static": "Hello", "title.$": "$.title", "name.$": "$customerName", // With $customerName declared as a variable "not-evaluated": "$customerName" } }
# Sample after conversion to JSONata { "QueryLanguage": "JSONata", // Set explicitly; could be set and inherited from top-level "Type": "Task", ... "Arguments": { // JSONata states do not have Parameters "static": "Hello", "title": "{% $states.input.title %}", "name": "{% $customerName %}", // With $customerName declared as a variable "not-evaluated": "$customerName" } }

Con la entrada { "title" : "Doctor" } y la variable customerName asignadas a"María", ambas máquinas de estado producirán el siguiente resultado en JSON:

{ "static": "Hello", "title": "Doctor", "name": "María", "not-evaluated": "$customerName" }

En el siguiente diagrama, puede ver una representación gráfica que muestra cómo la conversión JSONPath (izquierda) a JSONata (derecha) reducirá la complejidad de los pasos en sus máquinas de estado:

Diagrama que compara los campos de los JSONata estados JSONPath y los estados.

Si lo desea, puede seleccionar y transformar los datos de la entrada de estado en argumentos para enviarlos a la acción integrada. A continuación JSONata, puedes (opcionalmente) seleccionar y transformar los resultados de la acción para asignarlos a las variables y para obtener el estado de salida.

Nota: Los pasos de asignación y salida se producen en paralelo. Si decide transformar los datos durante la asignación de variables, esos datos transformados no estarán disponibles en el paso de salida. Debe volver a aplicar la JSONata transformación en el paso de salida.

Diagrama lógico de un estado que utiliza un lenguaje de JSONata consulta.

QueryLanguage campo

En las definiciones de ASL de su flujo de trabajo, hay un QueryLanguage campo en el nivel superior de la definición de una máquina de estados y en los estados individuales. Al establecer estados QueryLanguage internos individuales, puede adoptarlos de forma incremental JSONata en una máquina de estados existente en lugar de actualizarla de una sola vez.

El QueryLanguage campo se puede configurar en "JSONPath" o"JSONata". Si se omite el QueryLanguage campo de nivel superior, el valor predeterminado es. "JSONPath" Si un estado contiene un QueryLanguage campo de nivel estatal, Step Functions utilizará el lenguaje de consulta especificado para ese estado. Si el estado no contiene ningún QueryLanguage campo, utilizará el idioma de consulta especificado en el campo de nivel superiorQueryLanguage.

Escribir JSONata expresiones en cadenas JSON

Cuando una cadena del valor de un campo ASL, un campo de objeto JSON o un elemento de matriz JSON está rodeada de {% %} caracteres, esa cadena se evaluará como JSONata . Tenga en cuenta que la cadena debe {% empezar sin espacios iniciales y debe terminar %} sin espacios finales. Si se abre o cierra la expresión de forma incorrecta, se producirá un error de validación.

Presentamos algunos ejemplos:

  • "TimeoutSeconds" : "{% $timeout %}"

  • "Arguments" : {"field1" : "{% $name %}"}en un estado Task

  • "Items": [1, "{% $two %}", 3]en un Map estado

No todos los campos de ASL son aceptables. JSONata Por ejemplo, el Type campo de cada estado debe estar establecido en una cadena constante. Del mismo modo, el Resource campo del Task estado debe ser una cadena constante. El Items campo de Map estado aceptará una matriz JSON o una JSONata expresión que deba dar como resultado una matriz.

Variable reservada: $states

Step Functions define una única variable reservada llamada $states. En JSONata los estados, se asignan las siguientes estructuras $states para su uso en JSONata las expresiones:

# Reserved $states variable in JSONata states $states = { "input": // Original input to the state "result": // API or sub-workflow's result (if successful) "errorOutput": // Error Output (only available in a Catch) "context": // Context object }

Al introducir un estado, Step Functions asigna la entrada de estado a $states.input. El valor de se $states.input puede usar en todos los campos que aceptan JSONata expresiones. $states.inputsiempre hace referencia a la entrada de estado original.

Para TaskParallel, y Map dice:

  • $states.resultse refiere al resultado bruto de la API o del subflujo de trabajo si se ha realizado correctamente.

  • $states.errorOutputhace referencia a la salida de error si la API o el subflujo de trabajo fallaron.

    $states.errorOutputse puede usar en el Catch campo Assign oOutput.

Al crear, actualizar $states.result o $states.errorOutput validar la máquina de estados, se detectará si se intenta acceder a campos y estados en los que no se pueda acceder a ellos.

El $states.context objeto proporciona a sus flujos de trabajo información sobre su ejecución específicaStartTime, como el token de la tarea y la entrada inicial del flujo de trabajo. Para obtener más información, consulte Acceso a los datos de ejecución desde el objeto Context en Step Functions .

Manejo de errores de expresión

En tiempo de ejecución, JSONata la evaluación de la expresión puede fallar por diversos motivos, como los siguientes:

  • Error de tipo: una expresión, por ejemplo{% $x + $y %}, fallará si $y es $x o no es un número.

  • Incompatibilidad de tipos: una expresión puede dar como resultado un tipo que el campo no aceptará. Por ejemplo, el campo TimeoutSeconds requiere una entrada numérica, por lo que la expresión {% $timeout %} fallará si $timeout devuelve una cadena.

  • Valor fuera del rango: se producirá un error en una expresión que produzca un valor que esté fuera del rango aceptable para un campo. Por ejemplo, una expresión como esta {% $evaluatesToNegativeNumber %} fallará en el TimeoutSeconds campo.

  • No se devuelve un resultado: JSON no puede representar una expresión de valor indefinido, por lo que la expresión {% $data.thisFieldDoesNotExist %} generaría un error.

En cada caso, el intérprete arrojará el error:States.QueryEvaluationError. Los estados de tarea, mapa y paralelo pueden proporcionar un Catch campo para detectar el error y un Retry campo para volver a intentarlo en caso de error.

Convertir de a JSONPath JSONata

En las siguientes secciones se comparan y explican las diferencias entre el código escrito con JSONPath y JSONata.

No más campos de ruta

El ASL requiere que los desarrolladores usen Path versiones de los campos, por ejemploTimeoutSecondsPath, para seleccionar un valor de los datos de estado cuando los usan JSONPath. Cuando los usa JSONata, deja de usar Path campos porque ASL interpretará automáticamente JSONata las expresiones {% %} cerradas en campos que no sean de Path, como. TimeoutSeconds

  • JSONPath ejemplo heredado: "TimeoutSecondsPath": "$timeout"

  • JSONata : "TimeoutSeconds": "{% $timeout %}"

Del mismo modo, el Map estado se ItemsPath ha sustituido por el Items campo que acepta una matriz JSON o una JSONata expresión que debe dar como resultado una matriz.

Objetos JSON

ASL usa el término plantilla de carga útil para describir un objeto JSON que puede contener JSONPath expresiones Parameters y valores de ResultSelector campo. ASL no utilizará el término plantilla de carga útil JSONata porque la JSONata evaluación se realiza para todas las cadenas, independientemente de que se produzcan por sí solas o dentro de un objeto JSON o una matriz JSON.

No más. $

ASL requiere que añadas '.$' a los nombres de los campos de las plantillas de carga útil que vayas a utilizar JSONPath y a las funciones intrínsecas. Al especificar"QueryLanguage":"JSONata", ya no se utiliza la convención '.$' para los nombres de campo de objetos JSON. En su lugar, encierras las JSONata expresiones entre {% %} caracteres. Se utiliza la misma convención para todos los campos con valores de cadena, independientemente de la profundidad con la que se encuentre el objeto dentro de otras matrices u objetos.

Argumentos y campos de salida

Si QueryLanguage se establece enJSONata, los campos de procesamiento de E/S antiguos se deshabilitarán (InputPath, ParametersResultSelector, ResultPath yOutputPath) y la mayoría de los estados tendrán dos campos nuevos: Arguments yOutput.

JSONata proporciona una forma más sencilla de realizar transformaciones de E/S en comparación con los campos utilizados con ellos. JSONPath JSONatasus características hacen que sean Arguments Output más capaces que los cinco campos anteriores. JSONPath Estos nuevos nombres de campo también ayudan a simplificar el ASL y a aclarar el modelo de transmisión y devolución de valores.

Los Output campos Arguments y (y otros campos similares, como los de un Map estadoItemSelector) aceptarán un objeto JSON, como:

"Arguments": { "field1": 42, "field2": "{% jsonata expression %}" }

O bien, puedes usar una JSONata expresión directamente, por ejemplo:

"Output": "{% jsonata expression %}"

La salida también puede aceptar cualquier tipo de valor JSON, por ejemplo:"Output":true,"Output":42.

Los Output campos Arguments y solo son compatibles JSONata, por lo que no es válido usarlos con flujos de trabajo que sí los utilicen JSONPath. Por el contrario InputPath ParametersResultSelector, solo se admiten los campos ResultPathOutputPath,,,, y otros JSONPath campos JSONPath, por lo que no es válido utilizar campos basados en rutas cuando se utilizan JSONata como flujo de trabajo de nivel superior o como lenguaje de consulta de estado.

Aprueba el estado

El estado opcional Resultado en una aprobación se trataba anteriormente como el resultado de una tarea virtual. Con el idioma JSONata seleccionado como flujo de trabajo o consulta de estado, ahora puede usar el nuevo campo de salida.

Elija el estado

Cuando se utilizan JSONPath, los estados de elección tienen una entrada Variable y numerosas rutas de comparación, como las siguientesNumericLessThanEqualsPath:

# JSONPath choice state sample, with Variable and comparison path "Check Price": { "Type": "Choice", "Default": "Pause", "Choices": [ { "Variable": "$.current_price.current_price", "NumericLessThanEqualsPath": "$.desired_price", "Next": "Send Notification" } ], }

Con JSONata, el estado de elección tiene un Condition lugar en el que puede usar una JSONata expresión:

# Choice state after JSONata conversion "Check Price": { "Type": "Choice", "Default": "Pause" "Choices": [ { "Condition": "{% $current_price <= $states.input.desired_priced %}", "Next": "Send Notification" } ]

Nota: Las variables y los campos de comparación solo están disponibles para JSONPath. La condición solo está disponible para JSONata.

JSONata ejemplos

Los siguientes ejemplos se pueden crear en Workflow Studio para experimentar con ellos JSONata. Puede crear y ejecutar las máquinas de estados o utilizar el estado de prueba para transferir datos e incluso modificar la definición de la máquina de estados.

Ejemplo: entrada y salida

En este ejemplo se muestra cómo $states.input utilizar la entrada de estado y el Output campo para especificar la salida de estado cuando se opta por ello JSONata.

{ "Comment": "Input and Output example using JSONata", "QueryLanguage": "JSONata", "StartAt": "Basic Input and Output", "States": { "Basic Input and Output": { "QueryLanguage": "JSONata", "Type": "Succeed", "Output": { "lastName": "{% 'Last=>' & $states.input.customer.lastName %}", "orderValue": "{% $states.input.order.total %}" } } } }

Cuando el flujo de trabajo se ejecuta con lo siguiente como entrada:

{ "customer": { "firstName": "Martha", "lastName": "Rivera" }, "order": { "items": 7, "total": 27.91 } }

El estado de prueba o la ejecución de la máquina de estados devolverá la siguiente salida JSON:

{ "lastName": "Last=>Rivera", "orderValue": 27.91 }
Captura de pantalla que muestra la entrada y la salida de un estado bajo prueba.

Ejemplo: filtrar con JSONata

Puede filtrar los datos con los operadores de JSONata ruta. Por ejemplo, imagine que tiene una lista de productos como entrada y solo quiere procesar productos que contienen cero calorías. Puede crear una definición de máquina de estados con la siguiente ASL y probar el FilterDietProducts estado con la entrada de ejemplo que aparece a continuación.

Definición de máquina de estados para filtrar con JSONata

{ "Comment": "Filter products using JSONata", "QueryLanguage": "JSONata", "StartAt": "FilterDietProducts", "States": { "FilterDietProducts": { "Type": "Pass", "Output": { "dietProducts": "{% $states.input.products[calories=0] %}" }, "End": true } } }

Ejemplo de entrada para la prueba

{ "products": [ { "calories": 140, "flavour": "Cola", "name": "Product-1" }, { "calories": 0, "flavour": "Cola", "name": "Product-2" }, { "calories": 160, "flavour": "Orange", "name": "Product-3" }, { "calories": 100, "flavour": "Orange", "name": "Product-4" }, { "calories": 0, "flavour": "Lime", "name": "Product-5" } ] }

Resultado de probar el paso en su máquina de estados

{ "dietProducts": [ { "calories": 0, "flavour": "Cola", "name": "Product-2" }, { "calories": 0, "flavour": "Lime", "name": "Product-5" } ] }
Ejemplo de salida para JSONata las expresiones que se están probando.

JSONata funciones proporcionadas por Step Functions

JSONata contiene bibliotecas de funciones para funciones de cadena, numéricas, de agregación, booleanas, de matriz, de objetos, de fecha/hora y de orden superior. Step Functions proporciona JSONata funciones adicionales que puede utilizar en sus JSONata expresiones. Estas funciones integradas sustituyen a las funciones intrínsecas de Step Functions. Las funciones intrínsecas solo están disponibles en los estados que utilizan el lenguaje de JSONPath consultas.

Nota: JSONata Las funciones integradas que requieren valores enteros como parámetros redondearán automáticamente los números no enteros proporcionados.

$partition: JSONata equivale a una función States.ArrayPartition intrínseca para particionar una matriz grande.

El primer parámetro es la matriz que se va a particionar, el segundo parámetro es un número entero que representa el tamaño del fragmento. El valor devuelto será una matriz bidimensional. El intérprete divide la matriz de entrada en varias matrices del tamaño especificado por el tamaño del fragmento. La longitud del último fragmento de matriz puede ser menor que la longitud de los fragmentos de matriz anteriores si el número de elementos restantes de la matriz es menor que el tamaño del fragmento.

"Assign": { "arrayPartition": "{% $partition([1,2,3,4], $states.input.chunkSize) %}" }

$range: JSONata equivalente a una función States.ArrayRange intrínseca para generar una matriz de valores.

Esta función toma tres argumentos. El primer argumento es un número entero que representa el primer elemento de la nueva matriz, el segundo argumento es un número entero que representa el elemento final de la nueva matriz y el tercer argumento es el entero con valor delta para los elementos de la nueva matriz. El valor devuelto es una matriz de valores recién generada que va desde el primer argumento de la función hasta el segundo argumento de la función, con los elementos intermedios ajustados por el delta. El valor delta puede ser positivo o negativo, lo que incrementará o disminuirá cada elemento desde el último hasta alcanzar o superar el valor final.

"Assign": { "arrayRange": "{% $range(0, 10, 2) %}" }

$hash: JSONata equivalente a la función States.Hash intrínseca para calcular el valor hash de una entrada determinada.

Esta función toma dos argumentos. El primer argumento es la cadena de origen que se va a codificar. El segundo argumento es una cadena que representa el algoritmo de hash para el cálculo del hash. El algoritmo de hash debe tener uno de los siguientes valores:"MD5",,, "SHA-1""SHA-256","SHA-384". "SHA-512" El valor devuelto es una cadena del hash calculado de los datos.

Esta función se creó porque no JSONata admite de forma nativa la capacidad de calcular hashes.

"Assign": { "myHash": "{% $hash($states.input.content, $hashAlgorithmName) %}" }

$random: JSONata equivalente a la función States.MathRandom intrínseca para devolver un número aleatorio n donde. 0 ≤ n < 1

La función utiliza un argumento entero opcional que representa el valor inicial de la función aleatoria. Si utiliza esta función con el mismo valor de inicio, devolverá un número idéntico.

Esta función sobrecargada se creó porque la JSONata función integrada $randomno acepta un valor inicial.

"Assign": { "randNoSeed": "{% $random() %}", "randSeeded": "{% $random($states.input.seed) %}" }

$uuid: JSONata versión de la función intrínseca. States.UUID

La función no acepta argumentos. Esta función devuelve un UUID de la versión 4.

Esta función se creó porque no JSONata admite de forma nativa la capacidad de generar. UUIDs

"Assign": { "uniqueId": "{% $uuid() %}" }

$parse: JSONata función para deserializar cadenas JSON.

La función toma un JSON en cadena como único argumento.

JSONata admite esta funcionalidad a través de$eval; sin embargo, no $eval es compatible con los flujos de trabajo de Step Functions.

"Assign": { "deserializedPayload": "{% $parse($states.input.json_string) %}" }