Artículo
· 9 feb, 2023 Lectura de 4 min

Exportación a JSON - propiedades relacionales y propiedades heredadas

Por qué he decidido escribir esto

De nuevo se me planteó un reto que me costó algún tiempo y muchas pruebas obtener la mejor solución. Y ahora que lo logré, me gustaría compartir mi nuevo conocimiento.
 

¿Qué pasó?

En un namespace hay muchas clases similares, así que para dejarlas más sencillas hay una superclase con las propiedades comunes. Además, entre las clases hay relaciones. Yo tenía que hacer una exportación de una de esas clases a JSON, pero no podía cambiar las superclases, porque si no, podría descomponer el flujo de otras integraciones.

Lo que hizo todo realmente difícil fué que JSON no podía tener las propiedades de la superclase. ¡Ay! Podría hacer la exportación y sacarlas una a una, pero... ¿y si alguien cambia la superclase?

Y peor... ¿qué pasa con las propiedades relacionales? Si exportamos una propiedad relacional, exportamos otro objeto, con todas sus propiedades, pero tampoco podría tenerlas todas en el JSON.

La luz al final del túnel

Por suerte, siempre hay una luz al final del túnel, y mi luz son los XData.

La solución es muy simple: llamemos a la clase que tenía que exportar de ClaseParaExportacion, la clase de la propiedad relacional de ClaseRelacional y la superclase de SuperClase.

Así que tenemos:

Class proyecto.SuperClase Extends (%Persistent, %JSON.Adaptor) {
    Property PropiedadComun As %String;
}
Class proyecto.ClaseParaExportacion Extends proyecto.SuperClase {
    Property PropiedadParaExportacion As %String;
    Relationship RelacionParaExportacion As proyecto.ClaseRelacional [ Cardinality = many, Inverse = PropiedadRelacional ];
}
Class proyecto.ClaseRelacional Extends proyecto.SuperClase {
    Property NoExportarEsa As %String;
    Property ExportarEsa As %String;
    Relationship PropiedadRelacional As proyecto.ClaseParaExportacion [ Cardinality = one, Inverse = RelacionParaExportacion ];
}

En la ClaseParaExportacion, escribo el XData: debe haber un nombre y una etiqueta <Mapping> con las etiquetas <Property>. La etiqueta <Mapping> lleva el namespace del xml, o sea, xmlns="http://intersystems.com/jsonmapping", y las etiquetas <Property> llevan las propiedades descritas en   %JSON.MappingProperty¹ (de la documentación oficial).

El truco mágico es que todo lo que no está especificado en el mapeo será ignorado. Así que, si cambiamos la ClaseParaExportacion para:

Class proyecto.ClaseParaExportacion Extends proyecto.SuperClase {
    Property PropiedadParaExportacion As %String;
    Relationship RelacionParaExportacion As proyecto.ClaseRelacional [ Cardinality = many, Inverse = PropiedadRelacional ];
    XData MapeoJSON {
        <Mapping xmlns = "http://intersystems.com/jsonmapping">
            <Property Name = "PropiedadParaExportacion" FieldName = "Propiedad-JSON"/>
            <Property Name = "RelacionParaExportacion" FieldName = "ClaseRelacionalJSON"/>
        </Mapping>
    }
}

vamos a tener en el JSON algo como:

{
   "Propiedad-JSON":"valor",
   "ClaseRelacionalJSON": [
      {"PropiedadComun":"valor", "NoExportarEsa":"valor", "ExportarEsa":"valor"},
      {"PropiedadComun":"valor", "NoExportarEsa":"valor", "ExportarEsa":"valor"}
   ]
}

O sea, los nombres de la ClaseParaExportacion ya están listos, y solo las propiedades que queremos están en el JSON, pero la ClaseRelacional aún tiene trabajo que hacer.

Entonces, cambiamos la ClaseRelacional con un XData del mismo nombre para arreglar sus propiedades:

Class proyecto.ClaseRelacional Extends proyecto.SuperClase {
    Property NoExportarEsa As %String;
    Property ExportarEsa As %String;
    Relationship PropiedadRelacional As proyecto.ClaseParaExportacion [ Cardinality = one, Inverse = RelacionParaExportacion ];
    XData MapeoJSON
    {
        <Mapping xmlns = "http://intersystems.com/jsonmapping">
            <Property Name = "NoExportarEsa" Include="None"/>
            <Property Name = "ExportarEsa" Include="INOUT"/>
            <Property Name = "PropiedadComun" Include="INOUT"/>
        </Mapping>
    }
    
    
}

así vamos a tener en el JSON algo como:

{
   "Propiedad-JSON":"valor",
   "ClaseRelacionalJSON": [
      {"PropiedadComun":"valor", "ExportarEsa":"valor"},
      {"PropiedadComun":"valor", "ExportarEsa":"valor"}
   ]
}

que es lo que queremos. 

Es interesante observar que para la propiedad "NoExportarEsa" especifiqué una tag con Include="None". Eso es lo mismo que no poner ninguna tag para la propiedad.

¹ ved también %JSON.PropertyParameters para entender lo que hace cada propiedad.
 

¡Muchas gracias por leerme y espero que el artículo os resulte útil!

Podéis preguntarme si tenéis dudas o contactarme para que os ayude en algún caso especifico. ¡Estaré encantada de ayudar!

Comentarios (6)1
Inicie sesión o regístrese para continuar

Gracias por compartir tu experiencia Heloisa... mucha gente no sabe que tiene la posibilidad de decidir el formato de los objetos JSON... y que puede predefinir distintos formatos de exportación e importación y utilizar uno u otro según necesite.

Duda... las clases de las que quieres exportar objetos en JSON, ¿no deberían heredar de %JSON.Adaptor? O es que consigues hacerlo de otro modo?