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 utilizará .$ en nombres clave de objetos JSON.

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 de 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.

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

Nota: Los pasos Assign y Output 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 Output. 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 campo QueryLanguage en el nivel superior de la definición de una máquina de estado y en los estados individuales. Al configurar 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 campo QueryLanguage se puede definir en "JSONPath" o "JSONata". Si se omite el campo de nivel superior QueryLanguage, el valor predeterminado es "JSONPath". Si un estado contiene un campo de nivel de estado QueryLanguage, Step Functions utilizará el lenguaje de consulta especificado para ese estado. Si el estado no contiene ningún campo QueryLanguage, utilizará el lenguaje de consulta especificado en el campo de nivel superior QueryLanguage.

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 con {% sin espacios iniciales y debe terminar con %} sin espacios finales. Si 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 estado Map

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

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 los estados Task, Parallel, y Map:

  • $states.result hace referencia al resultado sin procesar de la API o del subflujo de trabajo si se ha realizado correctamente.

  • $states.errorOutput hace referencia a la salida de error si la API o el subflujo de trabajo produjo un error.

    $states.errorOutput se puede usar en Assign u Output del campo Catch.

Al crear, actualizar o validar la máquina de estado se detectarán los intentos de acceso a $states.result o $states.errorOutput en campos y estados que no son accesibles.

El objeto $states.context brinda a sus flujos de trabajo información sobre su ejecución específica, como StartTime, 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 .

Gestión 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, como {% $x + $y %}, fallará si $x o $y no es un número.

  • Incompatibilidad de tipo: una expresión podría evaluarse como 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 de rango: una expresión que produzca un valor que se encuentra fuera del rango aceptable de un campo producirá un error. Por ejemplo, una expresión como {% $evaluatesToNegativeNumber %} fallará en el campo TimeoutSeconds.

  • Error de devolución de 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 generará el error: States.QueryEvaluationError. Los estados Task, Map y Parallel pueden proporcionar un campo Catch para que detecte el error y un campo Retry para volver a intentarlo en caso de error.

Convertir de JSONPath a 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 TimeoutSecondsPath ejemplo, para seleccionar un valor de los datos de estado al usarlos 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, un objeto JSON o una JSONata expresión que debe dar como resultado una matriz u objeto.

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 campo de las plantillas de carga útil que vayas a utilizar y a las funciones intrínsecas. JSONPath Al especificar "QueryLanguage":"JSONata", ya no se utiliza la convención “.$” para nombres de campo de objetos JSON. En su lugar, encierra las expresiones entre caracteres JSONata . {% %} 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.

Campos Arguments y Output

Si QueryLanguage se establece enJSONata, los campos de I/O procesamiento 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 I/O transformaciones en comparación con los campos utilizados con JSONPath. JSONatasus características hacen que sea Arguments Output más capaz que los cinco campos anteriores con JSONPath. Estos nuevos nombres de campo también ayudan a simplificar el ASL y a aclarar el modelo para pasar y devolver valores.

Los campos Arguments y Output (y otros campos similares, como los del estado Map ItemSelector) 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.

Estado de paso

El Resultado opcional en un estado Pass 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.

Estado Choice

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 estado o utilizar el estado Pass para pasar datos e incluso modificar la definición de la máquina de estado.

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 Test o la ejecución de la máquina de estado devolverá la siguiente salida JSON:

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

Ejemplo: filtrar con JSONata

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

Indique la definición de la máquina con la que filtrar 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" } ] }

Salida de probar el paso en su máquina de estado

{ "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 consulta.

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 de fragmento. El valor de retorno 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 un número entero que representa el elemento final de la nueva matriz y el tercer argumento es el número entero del valor delta para los elementos de la nueva matriz. El valor de retorno 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 a la que se va a aplicar la función de hash. 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 de retorno 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 toma un argumento entero opcional que representa el valor de inicio 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 toma argumentos. Esta función devuelve un UUID v4.

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 representado en forma de 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) %}" }