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

How to create an array of Objects? #470

Closed
brunohkbx opened this issue Feb 23, 2017 · 15 comments
Closed

How to create an array of Objects? #470

brunohkbx opened this issue Feb 23, 2017 · 15 comments

Comments

@brunohkbx
Copy link

brunohkbx commented Feb 23, 2017

Its possible to create the folowing structure?
Using something like jsonObject["objects"]["object"]

{
    "objects": [
      {
        "object": {
          "address": "xxx"
        }},
      {
        "object": {
          "address": "xxx"
        }},
      {
        "object": {
          "address": "xxx"
        }}]
}
@brunohkbx brunohkbx changed the title How to create an array of Objects How to create an array of Objects? Feb 23, 2017
@nlohmann
Copy link
Owner

Yes, please have a look at the documentation: https://github.com/nlohmann/json#json-as-first-class-data-type

@fnc12
Copy link

fnc12 commented Feb 23, 2017

json j = {
    { "objects" , {
        { "object" , {
            { "address", "adr1" },
        }, },
        { "object" , {
            { "address", "adr2" },
        }, },
        { "object" , {
            { "address", "adr3" },
        }, },
    },
};

@brunohkbx
Copy link
Author

brunohkbx commented Feb 23, 2017

Thanks @nlohmann
@fnc12 I'm trying to do something like this :

json JsonObjects = json::array();
for (int i = 0; i <= 5; i++)
{
	JsonObjects.append(JsonObject)
}

Is it possible to append/Insert an object in the array?

@fnc12
Copy link

fnc12 commented Feb 23, 2017

Yes. Just like std::vector

auto jsonObjects = json::array();
for(auto i = 0; i <= 5; ++i) {
    jsonObjects.push_back(json::object());
}

@nlohmann
Copy link
Owner

Of course - it uses (more or less) the same API as std::vector, so you can use push_back. See https://nlohmann.github.io/json/ for an overview.

@brunohkbx
Copy link
Author

Thanks everyone.
Got it.

@moodboom
Copy link

Excellent. Would it be common enough to get mentioned in the main README doc? Would have helped me I know. Thanks nlohmann, love the class.

@arwinder-jaspal
Copy link

Yes. Just like std::vector

auto jsonObjects = json::array();
for(auto i = 0; i <= 5; ++i) {
    jsonObjects.push_back(json::object());
}

hi I am new to C++ and I am trying to achieve the same thing here.

Can anyone provide sample code for this problem?

Thank you in advance.

@code-blooded245
Copy link

code-blooded245 commented Nov 7, 2019

Can you please tell how to iterate over this type of json array ?

{
    "objects": [
        {
            "object": {
                "address": "xxx"
            }
        },
        {
            "object": {
                "address": "xxx"
            }
        },
        {
            "object": {
                "address": "xxx"
            }
        }
    ]
}

@nlohmann
Copy link
Owner

nlohmann commented Nov 7, 2019

// assuming you parse the JSON above to variable j

for (const auto& element : j["objects"])
{
    std::cout << element << std::endl;
}

This should output

{"object":{"address":"xxx"}}
{"object":{"address":"xxx"}}
{"object":{"address":"xxx"}}

Inside the loop, you can access the other elements with

element["object"]["address"]

@code-blooded245
Copy link

Thanks!

@siltau
Copy link

siltau commented Jul 15, 2020

Hi,
I'm having some trouble trying to access an element of an array of objects. The Json look like this:

{
"parentX":
    {
        "key1": "value1",
        "key2": "value2",
        "list":
        [
        {"0":{"keyA":"valueA"}},
        {"1":{"keyB":"valueB"}}
        ]
    },
"parentY":
    {
        "key1": "value1",
        "key2": "value2",
        "list":
        [
        {"0":{"keyA":"valueA"}},
        {"1":{"keyB":"valueB"}}
        ]
    }
}

Now I would like to accessand modify a specific element of "list" but I can't figure out how to do it.
I tried:

json["parentX"]["list"]["0"]["keyA"]          // WRONG
json["parentX"]["list"].at("0")["keyA"]      // WRONG

but they crash and probably I have misunderstood the documentation.
I'm doing correctly or is there another way to perform such operation?

@nlohmann
Copy link
Owner

The example you posted ins not valid JSON - there are commas missing. However, if you pass strings to operator[] or at(), an object is assumed. This should be the description of the exception that you should be getting. To access elements of arrays, pass numbers. For instance, json["parentX"]["list"][0] accessed the first element of the JSON array at json["parentX"]["list"].

@siltau
Copy link

siltau commented Jul 15, 2020

Thanks for the fast answer, and you are right, the Json was not valid as written but I just wrote it by hand to give an overview of what I was doing (I edited, should be fine now).

In the begin my objective was to access a specific element in an array, which I'm sure is present but I don't know the position, by using the underlying search/find features (like those used by operator[] or at() ) without scanning whole array, for both code clearness and possible performance issues. In my case the array is used as a circular buffer/FIFO, with parameterized size, so it can eventually grow.

In the end I realized that what I was trying is not possible so find out some option:

  • Using find() but I'm not sure is recursive (by trying seems not working the way I'm using it):
auto elementX = json["parentX"].find("0");
*elementX["keyA"] = "new_value";

auto elementY = json["parentY"].find("0");
*elementY["keyA"] = "new_value";
  • Using a for cicle scanning the whole array:
// 1
for (const auto& element : json["parentX"]["list"])
{
    // Have to check the key somehow and then access the value
    std::cout << element << std::endl;
}

// 2
for (auto it = json["parentX"]["list"].begin(); it !=json["parentX"]["list"].end(); ++it)
{
    std::cout << it.key() << " | " << it.value() << "\n";
}

// 3
for ( auto it:  json["parentX"]["list"].items() )
{
    std::cout << it.key() << " | " << it.value() << "\n";
}

But from information gatered seems I should scan the array twice, first time to find the position comparing the key, then again to modify the value.

Still testing, as soon as I find the solution I will post it.

@siltau
Copy link

siltau commented Jul 16, 2020

I've got what I was doing wrong and for sure I have to learn/deal more about APIs return values and how they work.
That is the solution to my problem:

for (auto& element :  json["parentX"]["list"])
{
    if(element.contains("0")==true)
    {
        element.at("0")["keyA"] = "newValue";
        break;
    }
}

maybe there is a clean/better way to do it because it seems a little bit ugly to me.

In my humble opinion the operator[] should also works on array when a string is passed hiding this search, in order to be "homogenous" with all value access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants