Guía práctica para crear y leer JSON

A continuación encontrarás traducido al castellano el artículo escrito por Gabriel Ludosanu y publicado originalmente en el Blog oficial de Xojo.

JSONItem es una clase nativa para trabajar con JSON. En función de como la utilices tratará tus datos como si fuese un diccionario estándar (pares de clave-valor) o bien como un array basado en índice cero.

Parte 1: Crear el JSON

Crear JSON desde cero implica instanciar un nuevo JSONItem y añadir datos sobre este. No crees JSON mediante la concatenación de cadenas, dado que tiende a “fallar” con facilidad, y tendrás que andar liado con caracteres de escape donde proceda… y además JSONItem hace que sea completamente innecesario.

La carga básica

Cuando simplemente necesitas enviar un objeto a un servicio web:

Var apiPayload As New JSONItem
apiPayload.Value("endpoint") = "/users/create"
apiPayload.Value("timestamp") = 1715423000
apiPayload.Value("forceSync") = True
 
// Obtén el resultado como cadena
Var jsonString As String = apiPayload.ToString
// {"endpoint":"/users/create","timestamp":1715423000,"forceSync":true}

Creando Arrays

Si estás creando una lista de etiquetas o IDs, utiliza el método .Add. Cuando llames a .Add, Xojo tratará la instancia de JSONItem como un array JSON de forma subyacente.

Var tags As New JSONItem
tags.Add("xojo")
tags.Add("desktop")
tags.Add("api")
 
Var jsonString As String = tags.ToString
// ["xojo","desktop","api"]

Anidaciones

La mayoría de las API requieren del uso de cargas de datos anidados. Puedes mapear este tipo de estructura mediante el uso de varios objetos JSONItem y asociarlos luego entre sí.

Var payload As New JSONItem
payload.Value("status") = "active"
 
Var user As New JSONItem
user.Value("id") = 982
user.Value("username") = "johndoe"
 
Var roles As New JSONItem
roles.Add("admin")
roles.Add("editor")
 
user.Value("roles") = roles // Asocia el array al objeto user
payload.Value("data") = user // Asocia el objeto user a la carga principal
 
Var jsonString As String = payload.ToString
// {"status":"active","data":{"id":982,"username":"johndoe","roles":["admin","editor"]}}

Parte 2: Parsear (interpretar) JSON

Cuando se trata de interpretar un JSON recibido, puedes pasar la cadena JSON recibida directamente en el Constructor de una nueva instancia JSONItem.

Leer la respuesta

Cuando un servidor devuelve una simple configuración o bien un token de autenticación puedes simplemente extraer los valores deseados.

Var rawJSON As String = "{""token"":""abc123xyz"",""expiresIn"":3600,""active"":true}"
Var response As New JSONItem(rawJSON)
 
Var token As String = response.Value("token")
Var expiresIn As Integer = response.Value("expiresIn")
Var isActive As Boolean = response.Value("active")

Manejar las claves opcionales con Lookup

Si utilizas .Value(“Key”) y la clave en cuestión no se encuentra en el JSON recibido Xojo lanzará una excepción de clave no encontrada (KeyNotFoundException). En vez de escribir el típico código que contemple esta posibilidad y la detecte, como por ejemplo…

If response.HasKey("key") Then
// aquí se encuentra el código que extraería la información
End If

…es preferible utilizar .Lookup(), ya que te permitirá definir un valor por omisión en el caso de que no se encuentre dicha clave definida; y todo en una sola línea de código:

Var rawJSON As String = "{""username"":""johndoe""}"
Var response As New JSONItem(rawJSON)
 
// Devuelve "johndoe" dado que la clave está presente
Var user As String = response.Lookup("username", "anonymous") 
 
// Devuelve False porque "forceSync" no se encuentra en el elemento JSON
Var isSyncForced As Boolean = response.Lookup("forceSync", False) 

Recorrer un Array

Si una API te devuelve una lista con registros:

Var rawJSON As String = "[{""id"":1, ""name"":""Alice""}, {""id"":2, ""name"":""Bob""}]"
Var userList As New JSONItem(rawJSON)
 
For i As Integer = 0 To userList.Count - 1
  Var currentUser As JSONItem = userList.ValueAt(i)
 
  Var id As Integer = currentUser.Value("id")
  Var name As String = currentUser.Value("name")
 
  System.DebugLog(id.ToString + ": " + name)
Next

Profundizar con los Nodos anidados

Aquí es donde .Child() entra en juego. Mientras que .Value() devuelve una Variante genérica (que no puedes asociar directamente), el método .Child(“Key”) devuelve de forma explícita el objeto anidado como instancia JSONItem. Esto permite realizar una asociación sin dificultad.

Var rawJSON As String = "{""weather"":{""current"":{""temp"":22, ""condition"":""Sunny""}}}"
Var forecast As New JSONItem(rawJSON)
 
// Usa .Child() para obtener objetos, mientras que .Value() extraerá los datos primitivos finales 
Var temperature As Double = forecast.Child("weather").Child("current").Value("temp")
Var condition As String = forecast.Child("weather").Child("current").Value("condition")

Part 3: Identificar la estructura

Las API son notablemente inconsistentes. Chequea la propiedad .IsArray para conocer el tipo de estructura con la que debes de trabajar antes de parsearla, de modo que cuando la recorras no se produzca un error.

Var rawJSON As String = "[""apple"", ""banana"", ""orange""]"
Var parsedData As New JSONItem(rawJSON)
 
If parsedData.IsArray Then
  System.DebugLog("Looks like an array with " + parsedData.Count.ToString + " items.")
 
  For i As Integer = 0 To parsedData.Count - 1
    System.DebugLog(parsedData.ValueAt(i).StringValue)
  Next
Else
  System.DebugLog("It's a standard dictionary.")
  If parsedData.HasKey("data") Then
    System.DebugLog(parsedData.Value("data").StringValue)
  End If
End If

¡Y eso es todo! Para obtener más información sobre JSONItem, recuerda consultar la documentación en línea disponible desde este enlace.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *