Search code examples
c++arraysjsonexceptionjsoncpp

Jsoncpp - How do I read an array?


I'm stuck at trying to read an array from a Json file.

Here is the People.json file:

{
  "ID": [
    {
      "1": {
        "name": "Fred",
        "favouriteFood": "Cheese",
        "gender": "Male"
      }
    },
    {
      "2": {
        "name": "Bob",
        "favouriteFood": "Cake",
        "gender": "Male"
      }
    }
  ]
}

Here is the function that should read it:

Person choosePerson(int ID)
{
    Person Person;
    ifstream file("People.json");
    Json::Value root;
    Json::Reader reader;
    Json::FastWriter fastWriter;

    reader.parse(file, root);
    Person.id = ID;
    Person.name = fastWriter.write(root["data"][to_string(ID)]["name"]);
    Person.favFood = fastWriter.write(root["data"][to_string(ID)]["favouriteFood"]);
    Person.gender = fastWriter.write(root["data"][to_string(ID)]["gender"]);
    return Person;
}

After Running it I get a "Json::LogicError" exception.


Solution

  • Problem is your JSon which is badly designed. It is bad since objects have keys of unexpected values. Those "1" and "2" make things complicated.

    I do not see in documentation how to get list of keys of a JSon object.
    Ok I've found getMemberNames(), but you try use it yourself. IMO it would be better to fix this JSon.

    So after fixing JSon like this:

    {
      "ID":[
        {
          "id":"1",
          "name":"Fred",
          "favouriteFood":"Cheese",
          "gender":"Male"
        },
        {
          "id":"2",
          "name":"Bob",
          "favouriteFood":"Cake",
          "gender":"Male"
        }
      ]
    }
    

    Reading of it can look like this:

    struct Person {
        std::string id;
        std::string name;
        std::string favouriteFood;
        std::string gender;
    };
    
    Person personFromJSon(const Json::Value& json)
    {
        return {
            json["id"].asString(),
            json["name"].asString(),
            json["favouriteFood"].asString(),
            json["gender"].asString()
        };
    }
    
    std::vector<Person> personsFromJSon(const Json::Value& json)
    {
        if (!json.isArray()) return {};
        std::vector<Person> result;
        result.reserve(json.size());
        std::transform(json.begin(), json.end(), std::back_inserter(result), personFromJSon);
        return result;
    }
    
    std::vector<Person> personsFromJSon(std::istream& in)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        return personsFromJSon(root["ID"]);
    }
    

    Here is live demo.