0

i'm actually working on a little program and i need to read a json file. i'm using C++ and the nlohmann json libraries.

My current code

int main(int argc, const char** argv){
    ifstream ifs("Myjson.json");
    json j = json::parse(ifs);
    cout << "Front image path : "<< j["front"]["imagePath"]  << "\n";
    cout << "Back image path : " << j["back"]["imagePath"] << "\n";

    system("PAUSE");
    return 0;
}

MyJson.json

{
    "Side": [
        {
            "camera": "22344506",
            "width": 19860,
            "nbParts": 662,
            "wParts": 30,
            "height": 1600,
            "imagePath": "./Tchek_buffer/22344506.png"
        },
        {
            "camera": "22344509",
            "width": 5296,
            "nbParts": 662,
            "wParts": 8,
            "height": 1600,
            "imagePath": "./Tchek_buffer/22344509.png"
        },
    ],
    "front": {
        "camera": "22344513",
        "image": null,
        "width": 1200,
        "height": 1600,
        "imagePath": "./Tchek_buffer/22344513.png"
    },
    "back": {
        "camera": "22344507",
        "image": null,
        "width": 1600,
        "height": 1200,
        "imagePath": "./Tchek_buffer/22344507.png"
    },
}

I can easily read and display the "back" and the "front" object but i can't read the scanner object. i want to get the "imagePath" of all "scanner" object

i tried thing like

cout << "scanner image path : " << j["scanner"]["imagePath"] << "\n";
cout << "scanner image path : " << j["scanner[1]"]["imagePath"] << "\n";
cout << "scanner image path : " << j["scanner"[1]]["imagePath"] << "\n";

i only get "null" result

if someone can help me and explain me how i can make it work .

2 Answers2

2

Assuming scanner is in fact Side in the json.

Your trials did the following:

  • Access the "imagePath" property of the list
  • Access the "scanner[1]" property of the list
  • Access the "c" (second character) property of the list.

So the dirty way to go would be :

cout << "scanner image path : " << j["Side"][0]["imagePath"] << "\n";
cout << "scanner image path : " << j["Side"][1]["imagePath"] << "\n";

And the proper one would be:

for (auto& element : j["Side"])
  cout << "scanner image path : " << element["imagePath"] << "\n";
Jean-Bernard Jansen
  • 7,544
  • 2
  • 20
  • 17
  • The "proper way" depends on many things. If the size of the array is always 2 (for left-side and right-side), the proper way is not a range-based loop. ;-) – Caduchon Sep 20 '17 at 09:47
  • How does "for (auto& element : j["Side"]) cout << "scanner image path : " << element["imagePath"] << "\n";" work ? –  Sep 20 '17 at 09:51
  • As long as the invariant was not properly stated, I always assume a list to be of any size. – Jean-Bernard Jansen Sep 20 '17 at 09:51
  • 1
    @EyRaG_ have a look at "range based" for loops. It is the C++ equivalent of what other languages call the `foreach`. It is basically syntactic sugar to avoid the iterator pain. – Jean-Bernard Jansen Sep 20 '17 at 09:52
  • Note that it's only available from C++11. – Caduchon Sep 20 '17 at 09:55
  • Which is a given since C++11 is a requirement to use `nlohmann/json` – Jean-Bernard Jansen Sep 20 '17 at 09:57
  • I will have more than 2 side object so doing a loop will help . Thanks for your answers. i just don't understand the "&" after the "auto" and what "element" is but i still know how that work . for each j side element display imagepath –  Sep 20 '17 at 09:57
  • The `auto` is there to let C++ infer the type itself. The & is there to tell it to retrieve the element by non const reference. You could use just `auto` for a copy or `auto const&` for a const reference. Get some doc about C++ references and the `auto` keyword. `auto` is a major feature of C++11. Here, `element` has type `json&`. – Jean-Bernard Jansen Sep 20 '17 at 10:00
  • I'll check some doc right now . Thank you for your reply . I did not think I had an answer so quickly –  Sep 20 '17 at 11:36
  • @Jean-BernardJansen that's maybe a newbie question but , can't i change the loop syntaxe with something like for (i=0 , i < auto& element :J[scanner], i++) then put cout << "scanner image path : " << j["Side"][i]["imagePath"] << "\n"; –  Sep 20 '17 at 11:59
  • Yes you can. You can write `for (size_t i = 0; i < j["Side"].size(); ++i) { /* code */ }` – Jean-Bernard Jansen Sep 20 '17 at 12:20
  • Yea thx that's exqctly what i wanted, have a last question about vectorname.push_back, can i merge a string and a variable and put in in the same index ? Like this : vectorname.push_back("element" + i) –  Sep 20 '17 at 12:53
  • Well thats pretty out of scope. It wont work this way, you have to learn how to manipulate strings in C++. – Jean-Bernard Jansen Sep 20 '17 at 15:22
0

I suppose "Side" and "scanner" is equivalent in your question. You probably did a mismatch between the tags.

I don't know this library, but I suppose it's something like that:

cout << "scanner image path 1 : " << j["scanner"][0]["imagePath"] << "\n";
cout << "scanner image path 2 : " << j["scanner"][1]["imagePath"] << "\n";

You can find an example from documentation here.

Caduchon
  • 4,574
  • 4
  • 26
  • 67