Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to retrieve data from nested objects #1038

Closed
EtienneBerube opened this issue Apr 5, 2018 · 13 comments
Closed

Trying to retrieve data from nested objects #1038

EtienneBerube opened this issue Apr 5, 2018 · 13 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@EtienneBerube
Copy link

EtienneBerube commented Apr 5, 2018

Hi, I'm trying to map data from a Json file to individual objects in order to sort them and perform other operations on them. However, the data structure required is quite complex and makes it hard to navigate.
Here is a snippet of the Json file:

{
  "items":
  {
    "item":
    [
      {
        "id": "0001",
        "type": "donut",
        "name": "Cake",
        "ppu": 0.55,
        "batters":
        {
          "batter":
          [
            { "id": "1001", "type": "Regular" },
            { "id": "1002", "type": "Chocolate" },
            { "id": "1003", "type": "Blueberry" },
            { "id": "1004", "type": "Devil's Food" }
          ]
        },
        "topping":
        [
          { "id": "5001", "type": "None" },
          { "id": "5002", "type": "Glazed" },
          { "id": "5005", "type": "Sugar" },
          { "id": "5007", "type": "Powdered Sugar" },
          { "id": "5006", "type": "Chocolate with Sprinkles" },
          { "id": "5003", "type": "Chocolate" },
          { "id": "5004", "type": "Maple" }
        ]
      },
      [...] Other items could be there
    ]
  }
}

I cannot change the way it is organised. However, I cannot figure out how to properly get every element and extract it.

My current code:

ifstream input("sample.json");

    json json1;

    input >> json1;

    json json2 = json1["items"]["item"];

    for ( auto& item : json2.get<json::object_t>() ){
        Item *tempItem = new Item();

        tempItem->setId(item.at("id"));
        tempItem->setName(item.at("name"));
        tempItem->setType(item.at("type"));
        tempItem->setId(item.at("ppu"));
        //Trying to go in the array batters
        object_t temp_obj = item.at("batters");

        items.push_back(new Item());
    }

Note: Even then I get an error because json2.get<json::object_t>() returns a pair<>.

Thanks in advance!

@nlohmann
Copy link
Owner

nlohmann commented Apr 5, 2018

You could try

for (const auto& item : json1["items"]["item"])
{
    // check if item["batters"]["batter"] exists
    if (item.find("batters") != item.end() and
        item["batters"].find("batter") != item["batters"].end())
    {
        for (const auto& batter : item["batters"]["batter"])
        {
            std::cout << batter["id"] << ", " << batter["type"] << std::endl;
        }
    }
    
    // check if item["topping"] exists
    if (item.find("topping") != item.end())
    {
        for (const auto& batter : item["topping"])
        {
            std::cout << batter["id"] << ", " << batter["type"] << std::endl;
        }
    }
}

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels Apr 5, 2018
@EtienneBerube
Copy link
Author

This does answer my initial question, but now I get a parsing error.

    ifstream input;
    input.open(R"(C:\Users\Etienne\Documents\GitHub\Collaboration\assingment 5\sample.json)");

    json json1;

    input >> json1; //Error

    cout<<"after parse";

    json json2 = json1["items"]["item"];

For an unknown reason it doesn't accept the parsing.

@gregmarr
Copy link
Contributor

gregmarr commented Apr 6, 2018

What is the error?

@EtienneBerube
Copy link
Author

It just stops, no error or anything. It tried printing after each statement and it happens at the JSON parsing.

@nlohmann
Copy link
Owner

nlohmann commented Apr 6, 2018

Can you check whether you can print the file content? Can you run the code in a debugger?

@EtienneBerube
Copy link
Author

After a few hours trying to debug, I finally got it to compile properly (reinstalled MinGW, changed my paths, etc.). The above code that @nlohmann wrote is accurate and works fine!
Thanks for your support and quick answers

@nlohmann
Copy link
Owner

nlohmann commented Apr 8, 2018

Thanks for checking back!

@parthbir
Copy link

How can one push batter["id"] into another json object or vector.

I'm getting the following error for above query:
error:'batter' was not declared in this scope

@TobeyWins
Copy link

Hey, thanks for your example code.
I have one question regarding it.
The following returns 0

    const auto& output = jFile["properties"]["rules"]["output"];
    std::cout << (output.contains("somekey")) << std::endl;

while this returns 1

    for (const auto& output1 : jFile["properties"]["rules"]["output"])
    {
        std::cout << (output1.contains("somekey")) << std::endl;
    }

my debugger is unable to unpack the type so im just wondering, why is the first 0 and the second 1?

@nlohmann
Copy link
Owner

Can you share the complete code example and JSON file?

@TobeyWins
Copy link

TobeyWins commented Jul 21, 2021

thanks for you fast response.
Here is the original json

{
    "title": "Data Transform Configuration",
    "type": "generic",
    "properties": {
  
        "operations":[
            {
                "unique_id": "left_shift_1",
                "type": "operation_shift",
                "direction": "left",
                "bit_start": 0,
                "bit_length": 32,
                "bit_shift": 4
            }
        ],

        "rules": {
            
            "input": {},
            "output": [
                {
                    "lengthNumberType": "byte",
                    "dataLength":12,
                    "descritpion": "format either via references or direct in place, example shows in-place",
                    "format": [
                        {
                            "node_type": "text",
                            "unique_id": "1",
                            "content": "urn:epc:tag:grai-96:"
                        },
                        {
                            "node_type": "data",
                            "unique_id": "2",           
                            "byte": 1,
                            "bit_start": 0,         
                            "bit_length": 3,     
                            "format": "decimal_ascii"
                        }
                    ]   
                }
            ],

            "notify": {

            }
        }
    }
}

the example code did not contain that much more.
Just a read in of the above file

    std::ifstream i(configFilePath);
    i >> jFile;
    std::cout << jFile.dump(4) << std::endl;

where the following went with ok

    for (const auto &output : jFile["properties"]["rules"]["output"])
    {

        if (!(output.contains(Constants::KEY_LENGTH_NUMBER_TYPE)) ||
            !(output.contains(Constants::KEY_RULE_DATA_LENGTH)) ||
            !(output.contains(Constants::KEY_FORMAT)))
        {
            std::cout << "error while parsing. incomplete rule definition" << std::endl;
            return;
        }

    ...
    }

but when i used

const auto &output = jFile["properties"]["rules"]["output"]

instead of the for-loop it just gave 0 for the contains method

@nlohmann
Copy link
Owner

jFile["properties"]["rules"]["output"] seems to be an array. If you call contains directly on it, it will always return false, see https://json.nlohmann.me/api/basic_json/contains/.

If you iterate it in the for loop, output is a reference to a JSON object. Here, contains does what you expect.

@TobeyWins
Copy link

TobeyWins commented Jul 21, 2021

Thank you very much for the clarification!
As my debugger did refuse to show the exact type i did not notice the difference.
I checked with the type property but it returned object for both items.

Thank you for the fast response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

5 participants