En el desarrollo de Business Central, el manejo de datos en formato JSON es algo habitual, especialmente al trabajar con integraciones y servicios externos. Sin embargo, leer un JSON sin formato puede ser una tarea ardua. Por ello, he creado un procedimiento que convierte un texto JSON en una estructura clara y legible.
¡Vamos manos a la obra! 😌
🔍 Código Completo
Aquí tienes el procedimiento completo que permite formatear un texto JSON en Business Central:
// Procedimiento que da formato a un texto JSON.
// Se lee el texto JSON, se recorre su estructura y se genera un nuevo texto formateado.
procedure FormatJsonText(JsonText: Text): Text
var
TempJsonBuffer: Record "JSON Buffer" temporary;
JsonTextReaderWriter: Codeunit "Json Text Reader/Writer";
LastPropertyName: Text;
FormattedJson: Text;
begin
// Se lee el texto JSON y se carga en el buffer temporal.
JsonTextReaderWriter.ReadJSonToJSonBuffer(JsonText, TempJsonBuffer);
// Se recorre el buffer si tiene registros.
if TempJsonBuffer.FindSet() then
repeat
// Se evalúa el tipo de token para determinar la acción correspondiente.
case TempJsonBuffer."Token type" of
// Se almacena el nombre de la propiedad para su uso posterior.
TempJsonBuffer."Token type"::"Property Name":
LastPropertyName := TempJsonBuffer.Value;
// Se inicia un nuevo objeto JSON.
TempJsonBuffer."Token type"::"Start Object":
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStartObject(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteStartObject('');
// Se cierra un objeto JSON.
TempJsonBuffer."Token type"::"End Object":
JsonTextReaderWriter.WriteEndObject();
// Se inicia un nuevo array JSON.
TempJsonBuffer."Token type"::"Start Array":
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStartArray(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteStartArray('');
// Se cierra un array JSON.
TempJsonBuffer."Token type"::"End Array":
JsonTextReaderWriter.WriteEndArray();
// Se escribe una propiedad de tipo cadena.
TempJsonBuffer."Token type"::String:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStringProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
// Se escribe una propiedad de tipo numérico (entero o decimal).
TempJsonBuffer."Token type"::Integer,
TempJsonBuffer."Token type"::Decimal:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteNumberProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
// Se escribe una propiedad de tipo booleano.
TempJsonBuffer."Token type"::Boolean:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteBooleanProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
// Se escribe una propiedad con valor nulo.
TempJsonBuffer."Token type"::Null:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteNullProperty(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteNullValue();
end;
until TempJsonBuffer.Next() = 0;
// Se obtiene el texto JSON formateado.
FormattedJson := JsonTextReaderWriter.GetJSonAsText();
exit(FormattedJson);
end;
📖 Análisis Detallado del Código
Este procedimiento recorre un texto JSON, identifica su estructura y lo vuelve a escribir con formato. A continuación, se detalla el funcionamiento paso a paso.
1️⃣ Declaración de Variables
var
TempJsonBuffer: Record "JSON Buffer" temporary;
JsonTextReaderWriter: Codeunit "Json Text Reader/Writer";
LastPropertyName: Text;
FormattedJson: Text;
TempJsonBuffer
: Registro temporal para almacenar la estructura del JSON.JsonTextReaderWriter
: Codeunit que se encarga de leer y escribir JSON.LastPropertyName
: Almacena el nombre de la última propiedad leída.FormattedJson
: Contendrá el resultado final con formato.
2️⃣ Lectura del Texto JSON
JsonTextReaderWriter.ReadJSonToJSonBuffer(JsonText, TempJsonBuffer);
Se utiliza el JsonTextReaderWriter
para leer el texto JSON y cargar su contenido en el TempJsonBuffer
. Este paso es fundamental para recorrer la estructura después.
3️⃣ Recorrido del Buffer
if TempJsonBuffer.FindSet() then
repeat
Esta estructura permite recorrer el buffer si contiene registros. Por cada registro encontrado, se evalúa el tipo de token.
4️⃣ Análisis del Token
La estructura case
es el núcleo del procedimiento. Evalúa el tipo de token y ejecuta la acción correspondiente.
🏷️ Propiedades
TempJsonBuffer."Token type"::"Property Name":
LastPropertyName := TempJsonBuffer.Value;
Cuando se encuentra un nombre de propiedad, se guarda para utilizarlo al asignar el valor correspondiente.
📦 Objetos
- Inicio de un objeto:
TempJsonBuffer."Token type"::"Start Object":
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStartObject(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteStartObject('');
Si existe un nombre de propiedad, el objeto se asocia a esta. De lo contrario, se inicia un objeto sin nombre.
- Fin de un objeto:
TempJsonBuffer."Token type"::"End Object":
JsonTextReaderWriter.WriteEndObject();
Se cierra el objeto actual.
🔢 Arrays
- Inicio de un array:
TempJsonBuffer."Token type"::"Start Array":
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStartArray(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteStartArray('');
Funciona igual que para los objetos, pero en este caso se inicia un array.
- Fin de un array:
TempJsonBuffer."Token type"::"End Array":
JsonTextReaderWriter.WriteEndArray();
Se cierra el array actual.
🖋️ Valores de Distintos Tipos
- Cadenas:
TempJsonBuffer."Token type"::String:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteStringProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
Si hay una propiedad asociada, se escribe como una propiedad de tipo cadena. Si no, simplemente se escribe el valor.
- Números (enteros y decimales):
TempJsonBuffer."Token type"::Integer,
TempJsonBuffer."Token type"::Decimal:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteNumberProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
Mismo funcionamiento que con las cadenas, pero aplicando el tipo numérico.
- Booleanos:
TempJsonBuffer."Token type"::Boolean:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteBooleanProperty(LastPropertyName, TempJsonBuffer.Value);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteValue(TempJsonBuffer.Value);
Se aplican las mismas reglas, adaptando el método de escritura para valores booleanos.
- Nulos:
TempJsonBuffer."Token type"::Null:
if LastPropertyName <> '' then begin
JsonTextReaderWriter.WriteNullProperty(LastPropertyName);
LastPropertyName := '';
end else
JsonTextReaderWriter.WriteNullValue();
Si el valor es nulo, se escribe como null
.
5️⃣ Finalización y Resultado
Una vez recorridos todos los registros del buffer, se obtiene el JSON formateado:
FormattedJson := JsonTextReaderWriter.GetJSonAsText();
exit(FormattedJson);
Este texto se devuelve como resultado final.
🎯 Beneficios y Aplicaciones Prácticas
Este procedimiento es útil para:
- Depurar JSON: facilita la comprensión del contenido.
- Integraciones externas: al formatear datos recibidos de servicios web.
- Presentación clara: útil cuando se necesita almacenar o mostrar el JSON formateado.
En entornos donde se manejan integraciones complejas, disponer de un texto JSON legible puede ahorrar mucho tiempo a los desarrolladores.
🧠 Conclusión
Formatear un texto JSON en Business Central no tiene por qué ser complicado. Con este procedimiento, puedes convertir una estructura difícil de leer en un formato comprensible de manera eficiente.
Si quieres ver el código completo, está en GitHub.