lunes, 17 de julio de 2017

¿Cómo procesar/parse un objeto JSON ya creado?

Siguiendo el ejemplo anterior ¿Cómo crear objetos JSON de cero? ahora vamos a suponer que tenemos el siguiente objeto o string JSON:

{
 "Book-1":{
  "id":2587,
  "titulo":"Dalila la bella",
  "subtitulo":"Poesia sobre Dalila.",
  "autor":"Sr. Juan Perez",
  "isbn":"777345934500023",
  "categoria":["arte","poesia"]
 },
 "Book-2":{
  "id":3700,
  "titulo":"Simbad el Marino",
  "subtitulo":"Aventuras de Simbad.",
  "autor":"Agustin Sanchez Aguilar",
  "isbn":"9788431668594",
  "categoria":["arte","historietas"]
 }
}

Y queremos procesar, navegar o "parse" su contenido elemento por elemento: libro por libro y atributo por atributo.


Para empezar, pega el objeto JSON mostrado líneas arriba en un objeto Memo de un formulario, digamos que es Memo1 dentro de Form1.


Compilador clásico de Borland

Veamos el siguiente código utilizando el compilador clásico de Borland:
El siguiente código funcionará sin problema en CLANG C++11.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
 TJSONObject *mainObj = (TJSONObject*) TJSONObject::ParseJSONValue(
    TEncoding::ASCII->GetBytes(Memo1->Lines->Text),0);
 TJSONPair *xBookPair = NULL;
 TJSONObject *xBook = NULL;

 try {
  for (int idx = 0; idx < mainObj->Size(); idx++) {
   xBookPair = (TJSONPair*) mainObj->Get(idx);
   xBook = (TJSONObject*) xBookPair->JsonValue;
   for (int idy = 0; idy < xBook->Count ; idy++) {
    ShowMessage(xBookPair->JsonString->ToString() + ": " +
     xBook->Get(idy)->JsonString->ToString() + ": " +
     xBook->Get(idy)->JsonValue->ToString());
   }
  }
 } __finally {
  delete mainObj;
 }
}

Nota que no es necesario eliminar con la cláusula delete las variables xBookPair y xBook, porque éstas sólo son referencias de memoria del objeto principal mainObj. Es decir al eliminar mainObj estarás borrando de memoria toda esta variable el cual es todo su contenido.


CLANG C++v11

Ahora veamos el siguiente código utilizando CLANG C++v11:
Si has seguido el ejemplo anterior mencionado en las primeras líneas de esta entrada encontrarás que, para utilizar CLANG debemos desactivar el compilador clásico de Borland que viene activado por defecto.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
 auto *mainObj = (TJSONObject*)TJSONObject::ParseJSONValue(
   TEncoding::ASCII->GetBytes(Memo1->Lines->Text),
   0);
 for (auto *xObj : mainObj) {
  for (auto * xBook : (TJSONObject*) xObj->JsonValue) {
   ShowMessage(xObj->JsonString->ToString() + ": " +
     xBook->JsonString->ToString() + ": " +
     xBook->JsonValue->ToString());
  }
 }

}

Al utilizar este compilador el código se reduce notablemente, de 21 a 13 líneas de código. Notarás también que no es necesario utilizar try...__finally. Esto porque, con la cláusula auto las variables son eliminadas automáticamente cuando su contexto  {}  llega a su fin.

En ambos casos el código es multiplataforma.
Es todo, e
spero sirva de ayuda.