Artículo
· 22 ago, 2023 Lectura de 8 min

Trabajando con %JSON.Adaptor

En este artículo, analizo la clase %JSON.Adaptor. Esta clase es extremadamente útil para exportar datos a JSON serializado e importar objetos JSON y guardarlos en un objeto de clase.

Comenzaré con %JSON. Parámetros del adaptador. Los parámetros son una parte crucial de las operaciones de importación y exportación de JSON.

Si el nombre de su propiedad no es el mismo que el nombre de la clave JSON para exportar a un dispositivo externo o cargar los datos en un objeto mediante la importación, debe usar el parámetro %JSONFIELDNAME para definir el nombre del alias. Si no es así, se produce un "campo inesperado" en el error de entrada en el momento de la importación.

Class Samples.TestJSONAdaptor Extends (%Persistent, %JSON.Adaptor)
{
    Property Name As %String(%JSONFIELDNAME = "First_Name");
ClassMethod ExportToJSON()
{
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(1)
    Do obj.%JSONExport() 
}
}
Output
LEARNING>Do ##class(Samples.TestJSONAdaptor).ExportToJSON()
{"First_Name":"myFirstName"}

En determinadas situaciones, es posible que no desee exponer o quiera omitir ciertas propiedades (Nota: la propiedad se expondrá en JSON aunque esté definida como una keyword interna) en la salida JSON. Para evitar que el campo quede expuesto al mundo exterior, puede mencionar este parámetro %JSONINCLUDE. El valor predeterminado es INOUT.

  1. INPUTONLY: solo aceptará entradas y no exportará datos al mundo exterior.
  2. OUTPUTONLY: muestra los valores en el mundo exterior. Sin embargo, los valores nulos solo se pueden almacenar si este parámetro se mencionó en esta propiedad.
  3. NONE: la salida o entrada JSON nunca debe almacenarse ni recuperarse.
Class Samples.TestJSONAdaptor Extends (%Persistent, %JSON.Adaptor)
{
    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property Phone As %Integer(%JSONINCLUDE = "INPUTONLY");
    Property IsActive As %Boolean(%JSONINCLUDE = "OUTPUTONLY");
ClassMethod ExportToJSON()
{
    #; JSON Export ouput
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(1)
    Do obj.%JSONExport() 
    #; output >> {"First_Name":"myFirstName","IsActive":true}
    #; Object ouput
    Write obj.Phone 
    #; output >> 9639639636
}

Output
LEARNING>Do ##class(Samples.TestJSONAdaptor).ExportToJSON()
 {"First_Name":"myFirstName","IsActive":true} 
9639639636

Generalmente, la instancia no tiene ningún valor en las propiedades que no formen parte de la exportación JSON. Para incluir esas propiedades en la exportación JSON, es necesario incluir el parámetro %JSONNULL. La salida tendrá el valor predeterminado de nulo. Además, puede definir esta opción de parámetro globalmente dentro de su definición de clase específica en lugar de en un campo específico. Esto será aplicable a todos los campos.

Class Samples.TestJSONAdaptor Extends (%Persistent, %JSON.Adaptor)
{

    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property Phone As %Integer(%JSONINCLUDE = "INPUTONLY");
    Property IsActive As %Boolean(%JSONINCLUDE = "OUTPUTONLY");
    /// This field is available in JSON export
    Property JSONNULLDeclared As %String(%JSONNULL = 1);
    /// This field is not available in JSON export
    Property JSONNULLNotDeclared As %String;
ClassMethod ExportToJSON()
{
    #; JSON Export 
    #; JSONNULLDeclared and JSONNULLDeclared - values are empty in object
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(1)
    Do obj.%JSONExport() 
    #; output >> {"First_Name":myFirstName"","IsActive":true,"JSONNULLDeclared":null}
}
}
Output
LEARNING>Do ##class(Samples.TestJSONAdaptor).ExportToJSON()
{"First_Name":myFirstName"","IsActive":true,"JSONNULLDeclared":null}

Básicamente, las cadenas vacías en la entrada JSON se almacenan como $c(0). Si hay valores "" en las propiedades, no se mostrarán en JSON porque %JSONIGNORENULL. Verifique que se cumplan las condiciones de la cadena vacía y exporte los datos habilitando %JSONIGNORENULL = 1. Además, puede definir y utilizar esta opción de parámetro globalmente.

Class Samples.TestJSONAdaptor Extends (%Persistent, %JSON.Adaptor)
{

    Parameter %JSONNULL = 1; ///declared globally
    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property Phone As %Integer(%JSONINCLUDE = "INPUTONLY");
    Property IsActive As %Boolean(%JSONINCLUDE = "OUTPUTONLY");
    Property JSONNULLDeclared As %String(%JSONNULL = 1);
    Property JSONNULLNotDeclared As %String(%JSONIGNORENULL = 1);
ClassMethod ExportToJSON()
{
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(1)
    Do obj.%JSONExport() 
}
}
Output
LEARNING>Do ##class(Samples.TestJSONAdaptor).ExportToJSON()
{"First_Name":"myFirstName","IsActive":true,"JSONNULLDeclared":null,"JSONNULLDeclared":null,"JSONNULLNotDeclared":""}

En la definición de clase podremos tener referencias a clases persistentes o serial. Si está exportando la clase a JSON, también exporta todos los campos de la clase referida a JSON. Si prefiere exportar solo los identificadores en lugar del valor completo, puede usar %JSONREFERENCE.

Class Samples.TestJSONAdaptor Extends (%Persistent, %JSON.Adaptor)
{

    Parameter %JSONNULL = 1;
    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property Phone As %Integer(%JSONINCLUDE = "INPUTONLY");
    Property IsActive As %Boolean(%JSONINCLUDE = "OUTPUTONLY");
    Property JSONNULLDeclared As %String(%JSONNULL = 1);
    Property JSONNULLNotDeclared As %String(%JSONIGNORENULL = 1);
    Property SubClass As Samples.TestJSONAdaptor.SubClass(%JSONREFERENCE = "ID");
ClassMethod ExportToJSON()
{
    #; JSON Export 
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(1)
    Do obj.%JSONExport() 
}
}

output
LEARNING>d ##class(Samples.TestJSONAdaptor).ExportToJSON()
   {"First_Name":"Ashok","IsActive":true,"JSONNULLDeclared":null,"JSONNULLNotDeclared":"","SubClass":{"RefId":"a3295","TestProperty":"Test1"}} ; %JSONREFERENCE = "OBJECT"
LEARNING>d ##class(Samples.TestJSONAdaptor).ExportToJSON()
    {"First_Name":"myFirstName","IsActive":true,"JSONNULLDeclared":null,"JSONNULLDeclared":null,"JSONNULLNotDeclared":"","SubClass":"a321"} ; %JSONREFERENCE = "ID"

Uno de los parámetros más cruciales. Cuando carga el objeto JSON en un objeto de clase, puede haber un cambio que provoque que se agreguen campos inesperados al JSON. Se genera un error si no se agrega el parámetro %JSONIGNOREINVALIDFIELD. Habilitar este parámetro en la definición de su clase es muy beneficioso.

///Before enabling %JSONIGNOREINVALIDFIELD
Class Samples.TestJSONAdaptor1 Extends (%Persistent, %JSON.Adaptor)
{
    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property IsActive As %Boolean;
ClassMethod TestJSONImport()
{
    Set json = {"Name":"MytestNewName","IsActive":true}
    Set obj = ..%New()
    Set st = obj.%JSONImport(json)
    If $$$ISERR(st) w $SYSTEM.OBJ.DisplayError(st)
    Write obj.%Save()
}
}
output
LEARNING>Do ##class(Samples.TestJSONAdaptor1).TestJSONImport()
 
ERROR #9404: Unexpected field in input, Name, using class base mapping.11{"First_Name":null}
LEARNING>

///After enabling %JSONIGNOREINVALIDFIELD
Class Samples.TestJSONAdaptor1 Extends (%Persistent, %JSON.Adaptor)
{
    Parameter %JSONIGNOREINVALIDFIELD As BOOLEAN = 1;
    Property Name As %String(%JSONFIELDNAME = "First_Name");
    Property IsActive As %Boolean;
ClassMethod TestJSONImport()
{
    Set json = {"Name":"MytestNewName", "Phone":9639631236, "IsActive":true, "unspecified":"" }
    Set obj = ..%New()
    Set st = obj.%JSONImport(json)
    If $$$ISERR(st) w $SYSTEM.OBJ.DisplayError(st)
    Write "Save : ",obj.%Save(),!
    Do obj.%JSONExport()
}
}
LEARNING>Do ##class(Samples.TestJSONAdaptor).TestJSONImport()
Save : 1
{"First_Name":null,"IsActive":null,"JSONNULLDeclared":null,"JSONNULLNotDeclared":"","SubClass":null,"GblCharStrm":null,"GblBinStrm":null,"Decimal":null}
 

Además, algunos de los parámetros que rara vez se utilizan son '%JSONENABLED. Si no desea generar el JSON, los generadores de métodos de clase Adaptor no producen un método ejecutable. Establezca el parámetro en 0. A menos que se especifique lo contrario, el valor predeterminado es 1.

 

Métodos API nativos para el adaptador JSON

%JSONImport

Este es un método para importar el objeto JSON al objeto de clase actual. Este método verifica todos los tipos de datos de las propiedades con el tipo de datos clave-valor JSON y declara el valor de la propiedad. Puede consultar los códigos de muestra anteriores para la importación JSON.

Recuerde que el tipo de datos JSON debe ser el mismo que el tipo de datos de la propiedad al importar datos. Lo contrario generará un error.

Los valores de tipo de datos booleanos 0 o 1 no son iguales que los del tipo de datos JSON booleanos verdadero o falso. JSON debe tener verdadero/falso en lugar de 0 o 1.

Utilice siempre el bloque JSONFIELDNAME o XDataMapping para evitar errores inesperados de discrepancia de campos. 

Es mejor utilizar el parámetro %JSONIGNOREINVALIDFIELD para evitar errores de campos inesperados

%JSONExport

Un método típico para escribir el JSON serializado en el dispositivo actual. Siempre que exporte e importe un número de punto flotante con ceros finales, estos no forman parte de la salida JSON. Porque los tipos ObjectScript Decimal y IEEE Binary Numeric no consideran los ceros finales. Puede consultar los códigos de muestra anteriores para la exportación JSON.

%JSONExportToStream

Hay opciones de exportación adicionales disponibles en %JSON.Adaptor. Puede exportar su JSON como un Stream, utilizando %JSON ExportToStream.

ClassMethod TestEXportToStream()
{
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(12)
    Do obj.%JSONExportToStream(.stream) 
    Write stream,!
    If $IsObject(stream) {
        Write stream.Read($$$MaxLocalLength)
    }
    Return
}

Output
EARNING>d ##class(Samples.TestJSONAdaptor).TestEXportToStream()
3@%Library.FileCharacterStream
{"First_Name":"TestNameSetMethod","IsActive":true,"JSONNULLDeclared":null,"JSONNULLNotDeclared":"","SubClass":"a3256","GblCharStrm":"Test string added as the global character stream","Decimal":12}

%JSONExportToString

Puede exportar el objeto JSON como una cadena utilizando el método %JSONExportToString.

ClassMethod TestEXportToString()
{
    Set obj = ##class(Samples.TestJSONAdaptor).%OpenId(12)
    Do obj.%JSONExportToString(.string) 
    Write string
    Return
}
output
LEARNING>d ##class(Samples.TestJSONAdaptor).TestEXportToString()
{"First_Name":"TestSetMethod","IsActive":true,"JSONNULLDeclared":null,"JSONNULLNotDeclared":"","SubClass":"a3256","GblCharStrm":"Test string added as the global character stream","Decimal":12}
Comentarios (0)1
Inicie sesión o regístrese para continuar