7

I have this JSON object:

{"books":[
    {
      "author" : "Petr",
      "book_name" : "Test1",
      "pages" : 200,
      "year" : 2002
    },
    {
      "author" : "Petr",
      "book_name" : "Test2",
      "pages" : 0,
      "year" : 0
    },
    {
      "author" : "STO",
      "book_name" : "Rocks",
      "pages" : 100,
      "year" : 2002
    }
  ]
}   

For example, I need to find a book(s) which author key is equal to Petr. How can I do this? Right now I have this piece of code:

Json::Value findBook(){
    Json::Value root = getRoot();

    cout<<root["books"].toStyledString()<<endl; //Prints JSON array of books mentioned above

    string searchKey;
    cout<<"Enter search key: ";
    cin>>searchKey;

    string searchValue;
    cout<<"Enter search value: ";
    cin>>searchValue;

    Json::Value foundBooks = root["books"]???; // How can I get here a list of books where searchKey is equal to searchValue?
}

Thanks in advance.

Petr Shypila
  • 1,449
  • 9
  • 27
  • 47
  • 3
    You keep saying "it doesn't work". Please get into the habit of presenting concrete problem descriptions, along with _evidence_. "It doesn't work" is basically useless. – Lightness Races in Orbit Feb 15 '15 at 01:15
  • @LightnessRacesinOrbit Hi. I'm really sorry for that. I've marked Barry solution as correct and it's true. In my case the problem was with Jetbrains' IDE CLion, which is currently available only as EAP release. There was just some bug with IDE, when after compiling a project it has started old app. – Petr Shypila Feb 15 '15 at 09:35

2 Answers2

8

Something like this should do:

std::vector<Json::Value> booksByPeter(const Json::Value& root) {
    std::vector<Json::Value> res;
    for (const Json::Value& book : root["books"])  // iterate over "books"
    {
        if (book["author"].asString() == "Petr")   // if by "Petr"
        {
            res.push_back(book);                   // take a copy
        }
    }
    return res;                                    // and return
}

If not C++11, will instead have to do:

const Json::Value& books = root["books"];
for (Json::ValueConstIterator it = books.begin(); it != books.end(); ++it)
{
    const Json::Value& book = *it;
    // rest as before
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • thank you. I just thought there is some elegant jsoncpp built in function for these needs. – Petr Shypila Jan 12 '15 at 13:46
  • 2
    @PeterShipilo I'd be pretty surprised if there was - just doing it the straightforward way seems plenty elegant and simple to me. – Barry Jan 12 '15 at 14:35
3

You can iterate over JSON arrays as STL containers:

std::vector<Json::Value> SearchInArray(const Json::Value &json, const std::string &key, const std::string &value)
{
    assert(json.isArray());
    std::vector<Json::Value> results;
    for (size_t i = 0; i != json.size(); i++)
        if (json[i][key].asString() == value)
            results.push_back(json[i]);
    return results;
}

Use it like this:

std::vector<Json::Value> results = SearchInArray(json["books"], "author", "Petr");
Sga
  • 3,608
  • 2
  • 36
  • 47