Pregunta
· 25 feb, 2021

Exportar JSon parcial a un mensaje de respuesta

Hola a todos,

Tengo una operación de API que llama a un proceso externo. La respuesta es un gran json, pero solo quiero una parte del contenido completo.

Mi primer intento es:

 .....
// Se omite el código de preparación de la solicitud.
establecer tSC = ..Adapter.SendFormDataArray (.tHttpResponse, "POST", tHttpRequest ,,, tURL)
si $$$ ISERR (tSC) $$$ ThrowStatus (tSC)
// Obtén la respuesta directamente
establecer respuesta = ""
while (tHttpResponse.Data.AtEnd = 0) {
establecer respuesta = respuesta_tHttpResponse.Data.Read ()
}
// Convierta Json en un objeto genérico, obtenga el nodo returnValue.data y convierta a JSon nuevamente
set objJson = ## class (% DynamicObject).% FromJSON (respuesta)
establecer jsonReturnValue = objJson.returnValue.data.% ToJSON ()
$$$ TRACE ("Content ReturnValue:" _jsonReturnValue)
do ## class (% ZEN.Auxiliary.jsonProvider).% ConvertJSONToObject (jsonReturnValue, "MyMsg.PartialJson",. pResponse)
......

La respuesta de JSon es:

{
  "result": "OK",
  "returnValue": {
    "code": "0",
    "message": "Info",
    "data": {
      "ext_customer_id": "123456789",
      "customer_name": "FRANCISCO",
      "customer_surname_1": "LÓPEZ",
      "customer_surname_2": "DE LAS HERAS",
      "passport_id": "123456ZZZ",
      "dob": "1972-02-01",
      "sex": "M",
      "email": "kurro.lopez@gmail.com",
      "active": true
    }
  }
}

y la clase MyMsg.PartialJson es:

 Class MyMsg.PartialJson extiende Ens.Response
{
/// Id del usuario
Propiedad "ext_customer_id" como% String (MAXLEN = 1024);
/// Nombre del cliente
Propiedad "customer_name" como% String (MAXLEN = 1024);
/// Apellido cliente
Propiedad "customer_surname_1" como% String (MAXLEN = 1024);
/// apellido 2 cliente
Propiedad "customer_surname_2" como% String (MAXLEN = 1024);
/// Passport ID
Propiedad "passport_id" como% String (MAXLEN = 250);
/// Fecha de nacimiento
Propiedad dob As% String (MAXLEN = 20);
/// Sexo
Sexo de la propiedad como% String (MAXLEN = 10);
/// Correo electrónico
Correo electrónico de la propiedad como% String (MAXLEN = 1024);
/// Compruebe si el cliente está activo
Propiedad activa como% booleano;
}

Pero el objeto pResponse está vacío.

¿Hay algun error?

Atentamente
Kurro Lopez

Comentarios (4)2
Inicie sesión o regístrese para continuar

Hola Kurro,

¿En qué versión lo estás probando? Me imagino que no puedes utilizar %JSON.Adaptor.

En cualquier caso, lo acabo de probar en un irishealth-community:2020.3.0.221.0 y parece que funciona:

Class MyMsg.PartialJson Extends Ens.Response
{

Property "ext_customer_id" As %String(MAXLEN = 1024);

Property "customer_name" As %String(MAXLEN = 1024);

Property "customer_surname_1" As %String(MAXLEN = 1024);

Property "customer_surname_2" As %String(MAXLEN = 1024);

Property "passport_id" As %String(MAXLEN = 250);

Property dob As %String(MAXLEN = 20);

Property sex As %String(MAXLEN = 10);

Property email As %String(MAXLEN = 1024);

Property active As %Boolean;

ClassMethod Test()
{
    set file = ##class(%Stream.FileCharacter).%New()
    set file.Filename = "/test/data.json"
    set data = file.Read()
    set objJson = ##CLASS(%DynamicObject).%FromJSON(data)
    set jsonReturnValue = objJson.returnValue.data.%ToJSON()
    write !!,"** jsonReturnValue:",!,jsonReturnValue

    set sc = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(jsonReturnValue, "MyMsg.PartialJson", .pResponse)
    write !!,"** %ConvertJSONToObject: ",!,sc

    write !!,"** Converted object:",!
    zw pResponse
}

Y el resultado de llamar al método de prueba:

USER>do ##class(MyMsg.PartialJson).Test()


** jsonReturnValue:
{"ext_customer_id":"123456789","customer_name":"FRANCISCO","customer_surname_1":"LOPEZ","customer_surname_2":"DE LAS HERAS","passport_id":"123456ZZZ","dob":"1972-02-01","sex":"M","email":"kurro.lopez@gmail.com","active":true}

** %ConvertJSONToObject: 
1

** Converted object:
pResponse=5@MyMsg.PartialJson  ; <OREF>
+----------------- general information ---------------
|      oref value: 5
|      class name: MyMsg.PartialJson
| reference count: 2
+----------------- attribute values ------------------
|       %Concurrency = 1  <Set>
|             active = 1
|      customer_name = "FRANCISCO"
| customer_surname_1 = "LOPEZ"
| customer_surname_2 = "DE LAS HERAS"
|                dob = "1972-02-01"
|              email = "kurro.lopez@gmail.com"
|    ext_customer_id = 123456789
|        passport_id = "123456ZZZ"
|                sex = "M"
+-----------------------------------------------------

Gracias Alberto.

Puede que sea por la versión de Caché, dado que estamos usando la 2017.2.1

$ZV: Cache for Windows (x86-64) 2017.2.1 (Build 801_3U) Thu Apr 12 2018 10:02:23 EDT
Product version: Ensemble 2017.1
 
Hay muchas cosas que están funcionando bien en IRIS, y esperamos que pronto nuestro cliente haga la migración a IRIS, pero por ahora tenemos que hacer "malabarismos" con estas cosas.
 
Al final lo he tenido que mapear a mano una vez recibido los datos.
 
Un saludo,
Kurro

Hola Kurro,

Sí, como dices es probable que tenga que ver con la versión, además la función ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject() utiliza internamente el deprecado %zen.ProxyObject y es probable que el comportamiento haya sufrido correcciones desde entonces.

En cualquier caso, si te encuentras a veces restringido por la versión que utilizas y necesitas realizar mapeos a mano (simples) de propiedades puedes apoyarte en métodos generados.

Por ejemplo, esta clase provee un método generado - muy simple - para tener un CopyProperties que puedas invocar y copie las propiedades.

/// Clase auxiliar para copiar propiedades de objetos que tengan el mismo nombre
Class MyMsg.ObjCopy Extends %RegisteredObject
{

/// Método generado que copia las propiedades (con el mismo nombre) de un objeto en el actual
/// -obj: objeto del cual se quieren copiar las propiedades  
Method CopyProperties(ByRef obj) As %Status [ CodeMode = objectgenerator ]
{
    set properties = %compiledclass.Properties
    for i=1:1:properties.Count() {
        #dim prop As %Dictionary.CompiledProperty = properties.GetAt(i)
        if prop.Name'="",prop.Name'["%" {
            set propName = prop.Name
            if prop.Name["_" { 
                set propName = """"_prop.Name_""""
            }

            // set ..x = obj.x
            do %code.WriteLine(" set .."_propName _"=obj."_propName)
        }
    }
    quit 1
}

}

Por lo que en tu clase MyMsg.PartialJson sólo necesitas cambiar la herencia:

Class MyMsg.PartialJson Extends (Ens.Response, ObjCopy)

Y a continuación, puedes invocarlo de la siguiente manera para que te copie las propiedades (parciales) de %DynamicObject:

    set partialJsonObj = ##class(MyMsg.PartialJson).%New()
    do partialJsonObj.CopyProperties(objJson.returnValue.data)
    write !!,"** partialJsonObj (copied):",!
    zw partialJsonObj