Search code examples
c++jsonjsoncpp

Iterate an array from json using jsoncpp


I have the following json:

{
    "laureates": [{
        "id": "1",
        "firstname": "Wilhelm Conrad",
        "surname": "Röntgen",
        "born": "1845-03-27",
        "died": "1923-02-10",
        "bornCountry": "Prussia (now Germany)",
        "bornCountryCode": "DE",
        "bornCity": "Lennep (now Remscheid)",
        "diedCountry": "Germany",
        "diedCountryCode": "DE",
        "diedCity": "Munich",
        "gender": "male",
        "prizes": [{
            "year": "1901",
            "category": "physics",
            "share": "1",
            "motivation": "\"in recognition of the extraordinary services he has rendered by the discovery of the remarkable rays subsequently named after him\""
        }]
    }]
}

I have tried this:

bool ok = reader.parse(txt, root, false);

    if(! ok)
    {
        std::cout << "failed parse\n";
    }

std::vector<std::string> keys = root.getMemberNames();

for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
    {
        if (root[*it].isString())
        {
            std::string value = root[*it].asString();
            std::cout << value << std::endl;
        }
        else if (root[*it].isInt())
        {
             int value = root[*it].asInt();
             std::cout << value << std::endl;
        }
        else if (root[*it].isArray()){
            // what to do here?
        }
}

The code works fine, but the problem is when I have an array like "prizes". I can't realize how to iterate and show the values without hardcoded it.

Can anyone help me with this?

Thanks in advance.


Solution

  • I can't realize how to iterate and show the values without hardcoded it.

    I think the problem is that you don't have a great handle on recursion or the key->value nature of JSON, because when you have an array like "prizes", you could have a nested Json object, such as an array inside an array.

    You could use a recursion to handle that:

    #include <jsoncpp/json/json.h>
    
    #include <iostream>
    
    void PrintJSONValue(const Json::Value &val) {
      if (val.isString()) {
        std::cout << val.asString();
      } else if (val.isBool()) {
        std::cout << val.asBool();
      } else if (val.isInt()) {
        std::cout << val.asInt();
      } else if (val.isUInt()) {
        std::cout << val.asUInt();
      } else if (val.isDouble()) {
        std::cout << val.asDouble();
      } else {
      }
    }
    
    void HandleJsonTree(const Json::Value &root, uint32_t depth = 0) {
      depth += 1;
      if (root.size() > 0) {
        std::cout << '\n';
        for (Json::Value::const_iterator itr = root.begin(); itr != root.end();
             itr++) {
          // print space to indicate depth
          for (int tab = 0; tab < depth; tab++) {
            std::cout << " ";
          }
          std::cout << "key: ";
          PrintJSONValue(itr.key());
          std::cout << " ";
          HandleJsonTree(*itr, depth);
        }
      } else {
        std::cout << ", value: ";
        PrintJSONValue(root);
        std::cout << "\n";
      }
    }
    
    int main(int argc, char **argv) {
      std::string json = R"###(
            {
        "laureates": [
            {
                "id": "1",
                "firstname": "Wilhelm Conrad",
                "surname": "Röntgen",
                "born": "1845-03-27",
                "died": "1923-02-10",
                "bornCountry": "Prussia (now Germany)",
                "bornCountryCode": "DE",
                "bornCity": "Lennep (now Remscheid)",
                "diedCountry": "Germany",
                "diedCountryCode": "DE",
                "diedCity": "Munich",
                "gender": "male",
                "prizes": [
                    {
                        "year": "1901",
                        "category": "physics",
                        "share": "1",
                        "motivation": "in recognition of the extraordinary services he has rendered by the discovery of the remarkable rays subsequently named after him"
                    }
                ]
            }
        ]
    }
        )###";
      Json::Value root;
      Json::Reader reader;
      bool ok = reader.parse(json, root, false);
    
      if (!ok) {
        std::cout << "failed parse\n";
      }
    
      HandleJsonTree(root);
    }
    

    The output looks like this:

     key: laureates 
      key: 0 -- the first item of an array
       key: born , value: 1845-03-27
       key: bornCity , value: Lennep (now Remscheid)
       key: bornCountry , value: Prussia (now Germany)
       key: bornCountryCode , value: DE
       key: died , value: 1923-02-10
       key: diedCity , value: Munich
       key: diedCountry , value: Germany
       key: diedCountryCode , value: DE
       key: firstname , value: Wilhelm Conrad
       key: gender , value: male
       key: id , value: 1
       key: prizes 
        key: 0 -- the first item of an array
         key: category , value: physics
         key: motivation , value: in recognition of the extraordinary services he has rendered by the discovery of the remarkable rays subsequently named after him
         key: share , value: 1
         key: year , value: 1901
       key: surname , value: Röntgen