2011-01-26 20 views
20

Tengo una aplicación C++ que usa jsoncpp para decodificar una cadena JSON. He creado la siguiente función, pero solo me muestra los objetos de nivel superior ...Iteración a través de objetos en JsonCpp

¿Cómo obtengo que se vuelque toda la lista de objetos?

--Function--

SaveJSON(json_data); 

bool CDriverConfigurator::PrintJSONTree(Json::Value & root, unsigned short depth /* = 0 */) 
{ 
    printf(" {type=[%d], size=%d} ", root.type(), root.size()); 

    if(root.size() > 0) { 
     for(Json::ValueIterator itr = root.begin() ; itr != root.end() ; itr++) { 
      PrintJSONTree(itr.key(), depth+1); 
     } 
     return true; 
    } 

    // Print depth. 
    for(int tab = 0 ; tab < depth; tab++) { 
     printf("-"); 
    } 

    if(root.isString()) { 
     printf(" %s", root.asString().c_str()); 
    } else if(root.isBool()) { 
     printf(" %d", root.asBool()); 
    } else if(root.isInt()) { 
     printf(" %d", root.asInt()); 
    } else if(root.isUInt()) { 
     printf(" %d", root.asUInt()); 
    } else if(root.isDouble()) { 
     printf(" %f", root.asDouble()); 
    } 
    else 
    { 
     printf(" unknown type=[%d]", root.type()); 
    } 


    printf("\n"); 
    return true; 
} 

--- ---- entrada

{ 
    "modules":[ 
     { 
     "config":{ 
      "position":[ 
       129, 
       235 
      ] 
     }, 
     "name":"Modbus Task", 
     "value":{ 
      "DeviceID":"This is the name", 
      "Function":"01_READ_COIL_STATUS", 
      "Length":"99", 
      "Scan":"111", 
      "Type":"Serve" 
     } 
     }, 
     { 
     "config":{ 
      "position":[ 
       13, 
       17 
      ] 
     }, 
     "name":"Modbus Connection", 
     "value":{ 
      "Baud":"9600", 
      "timeout":"2.5" 
     } 
     }, 
     { 
     "config":{ 
      "position":[ 
       47, 
       145 
      ] 
     }, 
     "name":"Modbus Device", 
     "value":{ 
      "DeviceID":"55" 
     } 
     }, 
     { 
     "config":{ 
      "position":[ 
       363, 
       512 
      ] 
     }, 
     "name":"Function Something", 
     "value":{ 

     } 
     }, 
     { 
     "config":{ 
      "position":[ 
       404, 
       701 
      ] 
     }, 
     "name":"Function Something", 
     "value":{ 

     } 
     } 
    ], 
    "properties":{ 
     "Blarrg":"", 
     "description":"", 
     "name":"Modbus" 
    }, 
    "wires":[ 
     { 
     "src":{ 
      "moduleId":1, 
      "terminal":"modbus.connection.output" 
     }, 
     "tgt":{ 
      "moduleId":2, 
      "terminal":"modbus.connection.input" 
     } 
     }, 
     { 
     "src":{ 
      "moduleId":2, 
      "terminal":"modbus.device.output" 
     }, 
     "tgt":{ 
      "moduleId":0, 
      "terminal":"modbus.device.output" 
     } 
     }, 
     { 
     "src":{ 
      "moduleId":3, 
      "terminal":"dataOut" 
     }, 
     "tgt":{ 
      "moduleId":4, 
      "terminal":"dataIn" 
     } 
     }, 
     { 
     "src":{ 
      "moduleId":3, 
      "terminal":"dataIn" 
     }, 
     "tgt":{ 
      "moduleId":0, 
      "terminal":"data1" 
     } 
     } 
    ] 
} 

--Output--

{type=[7], size=3} {type=[4], size=0} - modules 
{type=[4], size=0} - properties 
{type=[4], size=0} - wires 

Respuesta

20

Usted tener algo de e Hay errores relacionados con el hecho de que aparentemente no se maneja bien la recursión o la naturaleza de valor clave de JSON y cómo se relaciona con la biblioteca que está utilizando. No he probado este código en absoluto, pero debería funcionar mejor.

void CDriverConfigurator::PrintJSONValue(const Json::Value &val) 
{ 
    if(val.isString()) { 
     printf("string(%s)", val.asString().c_str()); 
    } else if(val.isBool()) { 
     printf("bool(%d)", val.asBool()); 
    } else if(val.isInt()) { 
     printf("int(%d)", val.asInt()); 
    } else if(val.isUInt()) { 
     printf("uint(%u)", val.asUInt()); 
    } else if(val.isDouble()) { 
     printf("double(%f)", val.asDouble()); 
    } 
    else 
    { 
     printf("unknown type=[%d]", val.type()); 
    } 
} 

bool CDriverConfigurator::PrintJSONTree(const Json::Value &root, unsigned short depth /* = 0 */) 
{ 
    depth += 1; 
    printf(" {type=[%d], size=%d}", root.type(), root.size()); 

    if(root.size() > 0) { 
     printf("\n"); 
     for(Json::Value::const_iterator itr = root.begin() ; itr != root.end() ; itr++) { 
      // Print depth. 
      for(int tab = 0 ; tab < depth; tab++) { 
       printf("-"); 
      } 
      printf(" subvalue("); 
      PrintJSONValue(itr.key()); 
      printf(") -"); 
      PrintJSONTree(*itr, depth); 
     } 
     return true; 
    } else { 
     printf(" "); 
     PrintJSONValue(root); 
     printf("\n"); 
    } 
    return true; 
} 
+0

Exactamente lo que estaba buscando. Gracias. –

+0

@Steven smethurst: Lo que es realmente divertido es que nunca antes había mirado esa biblioteca en mi vida. :-) – Omnifarious

+0

@cegprakash: ¿Por qué eliminaste las etiquetas de "referencia"? – Omnifarious

6

Si usted está buscando para imprimir el JSON :: Valor, hay un method para ello:

Json::Value val; 
/*...build the value...*/ 
cout << val.toStyledString() << endl; 

Además, es posible que desee ver en la Json::StyledWriter, la documentación es here. Creo que imprime una versión amigable para los humanos. Además, Json::FastWriter, documentación here, imprime una forma más compacta.

+0

Esto produce la salida que estaba buscando pero estaba haciendo este ejercicio para aprender cómo caminar por el árbol JSON. Gracias –

-1

Hay una manera fácil de iterar sobre todos los campos en json :: value. Omití las cosas de printf.

#include "cpprest/json.h" 
#include "cpprest/filestream.h" 

using web::json::value; 
using std::wstring; 

static void printOneValue(const wstring &key, const double &value); 
static void printOneValue(const wstring &key, const bool &value); 
static void printOneValue(const wstring &key, const int &value); 
static void printOneValue(const wstring &key, const wstring &value); 
static void printOne(const wstring &key, const value &v, _num level); 
static void printTree(const value &v); 

static void printTree(const value &v) 
{ 
    if(!v.is_object()) 
     return; 

    try 
    { 
     printOne(wstring(), v, 0); 
    } 
    catch(...) 
    { 
     // error handling 
    } 
} 

static void printOne(const wstring &key, const value &v, _num level) 
{ 
    switch(v.type()) 
    { 
    case value::value_type::Number: 
     if(v.is_double()) 
      printOneValue(key, v.as_double()); 
     else 
      printOneValue(key, v.as_integer()); 
     break; 
    case value::value_type::Boolean: 
     printOneValue(key, v.as_bool()); 
     break; 
    case value::value_type::String: 
     printOneValue(key, v.as_string()); 
     break; 
    case value::value_type::Object: 
     for(auto iter : v.as_object()) 
     { 
      const wstring &k = iter.first; 
      const value &val = iter.second; 
      printOne(k, val, level+1); 
     } 
     break; 
    case value::value_type::Array: 
     for(auto it : v.as_array()) 
     { 
      printOne(key, it, level+1); 
     } 
     break; 
    case value::value_type::Null: 
    default: 
     break; 
    } 
} 

static void printOneValue(const wstring &key, const wstring &value) 
{ 
    // process your key and value 
} 

static void printOneValue(const wstring &key, const int &value) 
{ 
    // process your key and value 
} 

static void printOneValue(const wstring &key, const double &value) 
{ 
    // process your key and value 
} 

static void printOneValue(const wstring &key, const bool &value) 
{ 
    // process your key and value 
} 
+0

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y/o por qué resuelve el problema mejoraría el valor de la respuesta a largo plazo. Lea este [cómo-para-responder] (http://stackoverflow.com/help/how-to-answer) para proporcionar una respuesta de calidad. – thewaywewere

+0

¡El código de ejemplo aquí no está basado en JsonCpp, sino en una biblioteca completamente diferente! Entonces esta es una respuesta a una pregunta completamente diferente. –

Cuestiones relacionadas