Uso de las funciones de JSON
FileMaker Pro proporciona varias funciones de texto que permiten a la app personalizada analizar y modificar datos JSON de otras funciones de FileMaker o de otras fuentes, como servicios Web que transfieren datos en formato JSON a través de una API REST.
Para obtener más información sobre el formato de datos de JSON, consulte json.org.
Los ejemplos mostrados en este tema utilizan datos JSON de una panadería que pone su lista de productos a disposición de los clientes en formato JSON a través de una API REST. A continuación se devuelve la lista de las especialidades del día como datos de JSON en la variable $$JSON:
Establecer variable [ $url ; "https://bakery.example.com/rest/api/products" ]
Insertar desde URL [ Con diálogo: Inactivo; Destino: $$JSON ; $url ; Verificar certificados SSL ; opciones de cURL: "--data list=specials" ]
Para conocer los datos devueltos en $$JSON y utilizados en estos ejemplos, consulte Datos de JSON de ejemplo.
Aplicar formato a datos de JSON
Los datos de JSON no requieren espacios o finales de línea entre elementos. Sin embargo, para simplificar las lecturas de datos al depurar problemas, utilice la función JSONFormatElements, que añade tabuladores y caracteres de final de línea, como se muestra en Datos de JSON de ejemplo.
Analizar datos de JSON
Utilice las siguientes funciones de JSON para analizar datos de JSON, es decir, para obtener claves, valores, o matrices u objetos de JSON completos que puede procesar de forma adicional:
-
JSONGetElement: realiza consultas en los datos de JSON de un elemento (un objeto, una matriz o un valor).
-
JSONListKeys: enumera los nombres (claves) de objeto o los índices de matriz de los datos de JSON.
-
JSONListValues: enumera los valores de los datos de JSON
El primer parámetro de estas funciones, json
, especifica el campo de texto, la variable o la expresión de texto que contiene los datos de JSON válidos con los que se trabajará.
El segundo parámetro, keyOrIndexOrPath
, especifica la parte de los datos de JSON con los que se trabajará:
-
Clave: el nombre de un clave de un objeto de JSON.
-
Índice: el índice de un elemento de una matriz de JSON (el primer elemento tiene un índice 0).
-
Ruta: una cadena jerárquica de nombres de clave, índices de matriz o ambos elementos.
Se admiten los dos siguientes tipos de sintaxis para el parámetro keyOrIndexOrPath
: notación de puntos y notación de corchetes.
Sintaxis del parámetro |
Indica que |
|
Notación de puntos | Notación de corchetes | |
---|---|---|
|
|
El nivel raíz, si es el primer carácter (opcional en la notación de puntos) |
|
|
Elementos en el índice n de una matriz en el nivel raíz. |
|
|
La clave de un objeto denominado nombre en el nivel raíz. |
|
|
Un objeto denominado nombreC, que desciende de nombreB y nombreA. |
|
|
El primer elemento de la matriz del objeto nombreA, que es el tercer nivel de un conjunto de matrices anidadas. |
|
|
El último elemento de una matriz |
|
|
La posición después del último elemento de una matriz. Utilizarlo en la función JSONSetElement para añadir un elemento al final de una matriz. |
La diferencia entre la notación de puntos y la de corchetes es que, en lugar de utilizar puntos (.
) para separar los nombres de las claves, la notación de corchetes rodea los nombres de las claves con comillas simples ('
) y corchetes ([]
). Puede utilizar cualquiera de las dos notaciones en keyOrIndexOrPath
. Sin embargo, debe utilizar la notación de corchetes si los nombres de las claves incluyen puntos para que el analizador JSON pueda identificar correctamente el nombre completo de la clave. Por ejemplo, si una clave en la raíz de un objeto JSON es "layout.response"
, entonces keyOrIndexOrPath
será "['layout.response']"
.
El siguiente guión de ejemplo crea un registro para cada producto de una matriz JSON. Suponiendo que los Datos de JSON de ejemplo se han almacenado en la variable $$JSON, el guión utiliza JSONListValues para obtener el contenido de la matriz de productos como una lista de valores y usa ValueCount para determinar la cantidad de productos de la lista. Al crear un registro para un producto cada vez que pasa por el bucle, el guión utiliza GetValue para obtener el objeto JSON de un producto de la lista y establece los campos en los valores obtenidos mediante JSONGetElement. Debido a que las funciones JSON analizan todo el objeto JSON transferido, puede ser más eficaz utilizar las funciones JSON en objetos JSON más pequeños dentro de un bucle que se repite muchas veces.
Establecer variable [ $ProductList ; Valor: JSONListValues ( $$JSON ; "panadería.producto" ) ]
Establecer variable [ $ProductCount ; Valor: ValueCount ( $ProductList ) ]
Establecer variable [ $i; Valor: 1 ]
If [ $ProductCount > 0 ]
Loop [ Flush: Siempre ]
Nuevo registro/petición
Establecer variable [ $Product ; Valor: GetValue ( $ProductList ; $i ) ]
Establecer campo [ Productos::ID ; JSONGetElement ( $Product ; "id" ) ]
Establecer campo [ Productos::Precio ; JSONGetElement ( $Product ; "precio" ) ]
Establecer campo [ Productos::Existencias ; JSONGetElement ( $Product ; "existencias" ) ]
Confirmar registros/peticiones [ Con diálogo: Inactivo ]
Establecer variable [ $i ; Valor: $i + 1 ]
Exit Loop If [ $i > $ProductCount ]
End Loop
End If
Modificar y añadir elementos de datos de JSON
Para modificar valores y añadir elementos a los datos de JSON, utiliza la función JSONSetElement. Los parámetros json
y keyOrIndexOrPath
de esta función presentan el funcionamiento descrito en Analizar datos de JSON. Si keyOrIndexOrPath
especifica un elemento existente, se modifica el valor de ese elemento; si el elemento no existe, se añade uno nuevo.
JSONSetElement establece el elemento especificado en el parámetro valor.
Puede especificar cualquier valor de JSON válido, desde una cadena o número sencillos hasta una matriz o un objeto complejos.
El parámetro tipo
especifica el tipo de datos del valor
, por lo que el analizador de JSON seguirá reglas estrictas al administrar cada tipo de datos. Para obtener información sobre los tipos de datos admitidos, consulte función JSONSetElement. Para insertar datos en json
con un formato existente como elemento JSON válido, establezca type
en JSONRaw
.
En el siguiente ejemplo, se añaden los pares de clave-valor de un nuevo producto a un objeto de JSON vacío. A continuación, se añade el nuevo objeto al final de la matriz de productos de la variable $$JSON (consulte Datos de JSON de ejemplo).
Establecer variable [ $NewProduct ; Valor:
JSONSetElement ( "{}" ;
[ "id" ; "FB4" ; JSONString ] ;
[ "nombre" ; "Tarta vainilla" ; JSONString ] ;
[ "precio" ; 17,5 ; JSONNumber ] ;
[ "existencias" ; 12 ; JSONNumber ] ;
[ "categoría" ; "Tartas" ; JSONString ] ;
[ "especialidad" ; true ; JSONBoolean ]
) ]
Establecer variable [ $NextIndex ; Valor:
ValueCount (
JSONListKeys ( $$JSON ; "panadería.producto" )
) ]
Establecer variable [ $$JSON ; Valor:
JSONSetElement (
$$JSON ; "panadería.producto[" & $NextIndex & "]" ; $NewProduct ;
JSONObject
) ]
Otra función JSON que crea un elemento JSON es la función JSONMakeArray. Convierte una lista de valores en una matriz JSON. Para aceptar datos formateados de diferentes maneras, esta función permite especificar el carácter que separa cada valor y el tipo de datos JSON a utilizar.
Eliminar elementos de datos de JSON
Para eliminar un elemento, utilice la función JSONDeleteElement. Los parámetros json
y keyOrIndexOrPath
de esta función presentan el funcionamiento descrito en Analizar datos de JSON. El parámetro keyOrIndexOrPath
debe especificar un elemento existente en json
.
En el siguiente ejemplo, se elimina el elemento de la matriz de productos cuya clave "id" presenta el valor "FB3" en la variable $$JSON (consulte Datos de JSON de ejemplo).
Establecer variable [ $ProductCount ; Valor:
ValueCount (
JSONListKeys ( $$JSON ; "panadería.producto" )
) ]
Establecer variable [ $i ; Valor: 0 ]
If [ $ProductCount > 0 ]
Loop [ Flush: Siempre ]
Establecer variable [ $ID ; Valor:
JSONGetElement ( $$JSON ; "panadería.producto[" & $i & "]id" ) ]
If [ $ID = "FB3" ]
Establecer variable [ $$JSON ; Valor:
JSONDeleteElement ( $$JSON ; "panadería.producto[" & $i & "]" ) ]
Salir del guion [ Resultado de texto: 0 ]
End If
Establecer variable [ $i ; Valor: $i + 1 ]
Exit Loop If [ $i ≥ $ProductCount ]
End Loop
End If
Optimización del rendimiento de JSON
Cada vez que una función JSON analiza una entrada de texto, el analizador JSON crea una representación binaria (no de texto) para agilizar el procesamiento posterior del contenido JSON. Existe un mecanismo automático para analizar y almacenar en la memoria caché el contenido JSON y otro explícito: la función función JSONParse.
Aprovechar el almacenamiento en caché automático de JSON
El análisis sintáctico lleva su tiempo, por lo que las funciones JSON almacenan en la memoria caché la representación binaria del último contenido JSON analizado. Esto reduce la necesidad de volver a analizar el mismo contenido JSON más adelante. Solo se conserva una memoria caché automática. Cuando se analiza un valor de JSON diferente, se descarta el valor de JSON almacenado previamente en la memoria caché. El contenido JSON analizado solo existe en la memoria: en las variables, los parámetros de guión y los cálculos. Cuando se utiliza para establecer el valor de un campo, este se almacena en el campo como texto.
Por número de línea, en este ejemplo, se muestra cuándo se analiza el texto JSON almacenado inicialmente en $JSON1 y $JSON2 y cuándo no.
Establecer variable [ $id ; JSONGetElement ( $JSON1 ; "id" ) ]
Establecer variable [ $name ; JSONGetElement ( $JSON1 ; "nombre" ) ]
Establecer variable [ $price ; JSONGetElement ( $JSON2 ; "precio" ) ]
Establecer variable [ $category ; JSONGetElement ( $JSON1 ; "categoría" ) ]
-
$JSON1 se analiza y la representación binaria se guarda en la memoria caché.
-
No es necesario que se analice de nuevo $JSON1.
-
$JSON2 se analiza y se almacena en la memoria caché, sustituyendo al valor almacenado anteriormente.
-
$JSON1 se analiza de nuevo porque ya no se encuentra almacenado en la memoria caché.
Por lo tanto, para aprovechar las ventajas del almacenamiento automático en la memoria caché, es mejor trabajar con un valor de JSON cada vez (en el ejemplo anterior, intercambie las líneas 3 y 4 para evitar volver a analizar $JSON1).
Uso de JSONParse
Para analizar y almacenar explícitamente la representación binaria de un valor de JSON en una variable, así como en la memoria caché automática, utilice la función función JSONParse. El parámetro json
de la función es cualquier expresión de texto que se evalúe en datos JSON, ya sea texto con formato JSON en un campo o una cadena, o contenido JSON analizado en una variable.
En el siguiente ejemplo, se analiza texto JSON:
Establecer variable [ $JSON1 ; "{ \"producto\": {\"id\": \"FB1\"} }" ]
Establecer variable [ $JSON1 ; JSONParse ( $JSON1 ) ]
-
$JSON1 es solo la representación de texto, que presenta el siguiente aspecto:
{ "producto": {"id": "FB1"} }
-
Después de usar JSONParse:
-
La memoria caché automática contiene la representación binaria.
-
La variable $JSON1 contiene tanto la representación de texto como la binaria.
-
Si no se utiliza JSONParse, en este ejemplo:
Establecer variable [ $JSON1 ; "{ \"producto\": {\"id\": \"FB1\"} }" ]
Establecer variable [ $JSON2 ; JSONGetElement ( $JSON1 ; "producto") ]
-
$JSON1 es solo la representación de texto, como antes.
-
Después de usar JSONGetElement:
-
La memoria caché automática contiene la representación binaria.
-
$JSON2 contiene la representación binaria de
{"id": "FB1"}
. -
$JSON1 sigue siendo solo la representación de texto. Se ha analizado el texto, pero la representación binaria solo se encuentra en la memoria caché automática.
-
Compare eso con lo que sucede cuando añade JSONParse:
Establecer variable [ $JSON1 ; "{ \"producto\": {\"id\": \"FB1\"} }" ]
Establecer variable [ $JSON1 ; JSONParse ( $JSON1 ) ]
Establecer variable [ $JSON2 ; JSONGetElement ( $JSON1 ; "producto") ]
-
$JSON1 es solo la representación de texto, como antes.
-
Después de usar JSONParse:
-
La memoria caché automática contiene la representación binaria.
-
$JSON1 contiene tanto la representación de texto como la binaria.
-
-
Después de usar JSONGetElement:
-
$JSON2 contiene la representación binaria de
{"id": "FB1"}
.La representación de texto no se almacena en $JSON2 en este momento, sino que se genera posteriormente solo cuando es necesario.
-
Tenga en cuenta que JSONGetElement no necesitaba analizar $JSON1 en la línea 3, porque podía utilizar la representación binaria almacenada en la memoria caché con $JSON1 en la línea 2.
Al igual que analizar texto para obtener una representación binaria lleva su tiempo, lo mismo ocurre al convertir contenido JSON binario en texto. Por este motivo, el resultado de funciones JSON como JSONGetElement y JSONSetElement es solo la representación binaria. La representación de texto se crea solo cuando es necesario, como cuando se almacena una variable (como $JSON2) en un campo o se visualiza una variable en el visor de datos.
Puede utilizar la función complementaria JSONParsedState para descubrir si un valor de JSON especificado incluye el contenido JSON analizado, si el contenido JSON es válido y cuál es el tipo JSON.
Prácticas recomendadas
Cuando se procesan grandes estructuras JSON de forma repetida (especialmente en bucles) o se trabaja con varios elementos en datos JSON, el orden de las operaciones puede suponer una diferencia significativa en el rendimiento.
Para aprovechar las ventajas del almacenamiento automático en la memoria caché de JSON, es recomendable no alternar entre la carga de datos JSON de un campo para trabajar en él, cambiar a otro campo diferente para trabajar en él y, a continuación, volver al primer campo. Cada vez que una función JSON procesa un texto JSON diferente, el contenido JSON almacenado previamente en la memoria caché se descarta, por lo que el texto debe analizarse de nuevo. Por ejemplo, así se obtiene el rendimiento más lento:
# Ejemplo - No eficiente
Establecer variable [ $namel ; Valor: JSONGetElement ( Tabla::JSON1 ; "nombre" ) ]
Establecer variable [ $name2 ; Value: JSONGetElement ( Tabla::JSON2 ; "nombre" ) ]
Establecer variable [ $id1 ; Value: JSONGetElement ( Tabla::JSON1 ; "id" ) ]
Establecer variable [ $id2 ; Value: JSONGetElement ( Tabla::JSON2 ; "id" ) ]
Solo al reordenar los pasos de forma que realice todo el trabajo en los mismos datos JSON antes de trabajar en otros diferentes, la memoria caché automática trabaja a su favor, eliminando la necesidad de analizar los datos del mismo campo dos veces.
# Ejemplo - Mejor
Establecer variable [ $namel ; Valor: JSONGetElement ( Tabla::JSON1 ; "nombre" ) ]
Establecer variable [ $id1 ; Valor: JSONGetElement ( Tabla::JSON1 ; "id" ) ]
Establecer variable [ $name2 ; Valor: JSONGetElement ( Tabla::JSON2 ; "nombre" ) ]
Establecer variable [ $id2 ; Valor: JSONGetElement ( Tabla::JSON2 ; "id" ) ]
El método mejor y más flexible es utilizar la función JSONParse para obtener el texto JSON de cada fuente, analizarlo y almacenarlo en una variable. De esta forma, solo se analiza una vez. En ese caso, no importa en qué orden realice las operaciones posteriores (como obtener o establecer elementos), ya que esas funciones JSON pueden utilizar las variables, que contienen las representaciones binarias analizadas previamente.
# Ejemplo - El mejor
Establecer variable [ $JSON1 ; Valor: JSONParse ( Tabla::JSON1 ) ]
Establecer variable [ $JSON2 ; Valor: JSONParse ( Tabla::JSON2 ) ]
Establecer variable [ $namel ; Valor: JSONGetElement ( $JSON1 ; "nombre" ) ]
Establecer variable [ $name2 ; Valor: JSONGetElement ( $JSON2 ; "nombre" ) ]
Establecer variable [ $id1 ; Valor: JSONGetElement ( $JSON1 ; "id" ) ]
Establecer variable [ $id2 ; Valor: JSONGetElement ( $JSON2 ; "id" ) ]
Administrar errores en los datos de JSON
Si se produce un error al analizar el parámetro json
, la función de JSON devuelve "?" seguido de un mensaje de error del analizador de JSON.
Por ejemplo, cuando falta el signo ":" tras la clave "panadería" en Datos de JSON de ejemplo, este cálculo
JSONGetElement ( $$JSON ; "panadería.producto[0]id" )
devuelve este mensaje de error:
? * Línea 3, Columna 2
Falta ':' tras el nombre del miembro del objeto
* Línea 13, Columna 5
Espacio en blanco adicional después del valor JSON.
Para determinar si los datos de JSON son válidos antes de utilizarlos, use la función JSONFormatElements y compruebe si el primer carácter es "?". Por ejemplo:
Establecer variable [ $resultado ; Valor: JSONFormatElements ( $$JSON ) ]
If [ Quedan ( $resultado ; 1 ) = "?" ]
# $$JSON contiene datos de JSON no válidos.
End If
Para determinar si los datos JSON son válidos y de un tipo JSON específico antes de utilizarlos, otra posibilidad es utilizar la función función JSONGetElementType. Por ejemplo, para comprobar si $$JSON es un objeto JSON válido:
Establecer variable [ $resultado ; Valor: JSONGetElementType( $$JSON, "" ) ]
If [ $resultado ≠ JSONObject ]
# $$JSON contiene datos de JSON no válidos.
End If
Otra forma de detectar errores es con la función función JSONParsedState. Puede indicarle si los datos JSON se han analizado y son válidos y, si es así, de qué tipo de datos JSON se trata.
Establecer variable [ $result ; Valor: JSONParse ( $$JSON ) ]
Establecer variable [ $ParsedState ; Valor: JSONParsedState ( $result ) ]
If [ $ParsedState < 0 ]
# $$JSON se ha analizado, pero contiene datos JSON no válidos.
Else If [ $ParsedState = 0 ]
# $$JSON no se ha analizado.
Else If [ $ParsedState > 0 ]
# $$JSON se ha analizado y es válido. $ParsedState indica el tipo JSON
Establecer variable [ $type ; Valor:
Case (
$ParsedState = JSONString ; "El tipo JSON es JSONString" ;
$ParsedState = JSONNumber ; "El tipo JSON es JSONNumber" ;
$ParsedState = JSONObject ; "El tipo JSON es JSONObject" ;
$ParsedState = JSONArray ; "El tipo JSON es JSONArray" ;
$ParsedState = JSONBoolean ; "El tipo JSON es JSONBoolean" ;
$ParsedState = JSONNull ; "El tipo JSON es JSONNull"
)
]
Mostrar cuadro de diálogo personalizado [ $type ]
End If
Datos de JSON de ejemplo
En el siguiente ejemplo, los datos de JSON contienen un objeto "panadería" que tiene una matriz de tres objetos "producto", cada uno con varios pares clave-valor.
{
"panadería" :
{
"producto" :
[
{
"id" : "FB1",
"nombre" : "Rosquillas",
"precio": 1,99,
"existencias" : 43,
"categoría" : "Panes",
"especialidad" : true
},
{
"id" : "FB2",
"precio": 22,5,
"nombre" : "Tarta de chocolate",
"existencias" : 23,
"categoría" : "Cakes",
"especialidad" : true
},
{
"id" : "FB3",
"precio": 3,95,
"nombre" : "Baguette",
"existencias" : 34,
"categoría" : "Panes",
"especialidad" : true
}
]
}
}
Notas
-
El analizador de JSON conserva el orden de los elementos de la matriz, pero no el orden de los elementos de un objeto. Por lo tanto, es posible que las funciones de JSON devuelvan elementos de un objeto en un orden diferente al especificado.
-
En los datos JSON, los valores numéricos fraccionarios deben usar un punto "." como separador decimal independientemente del separador especificado por los formatos del sistema del equipo o los formatos utilizados cuando se creó el archivo de FileMaker Pro.