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

recursive data structures #277

Closed
froatsnook opened this issue Jul 4, 2016 · 4 comments
Closed

recursive data structures #277

froatsnook opened this issue Jul 4, 2016 · 4 comments

Comments

@froatsnook
Copy link

Hi, thanks for the great library :). I had a gotcha when working with a recursive data structure.

using namespace std;
using namespace nlohmann;
int main() {
    string text = "{\"A\":{\"id\":1,\"children\":{\"B\":{\"id\":2,\"children\":{\"C\":{\"id\":3,\"children\":{}}}}}}}";
    json data = json::parse(text);

    json& curr = data;
    curr = curr["A"]["children"];

    cout << "curr=" << curr.dump() << std::endl; // { B: ... } OK
    cout << "data=" << data.dump() << std::endl; // { B: ... } expected { A: ... }
}

I was able to work around this using a pointer:

    string text = "{\"A\":{\"id\":1,\"children\":{\"B\":{\"id\":2,\"children\":{\"C\":{\"id\":3,\"children\":{}}}}}}}";
    json data = json::parse(text);

    json* curr = &data;
    curr = &curr->operator[]("A").operator[]("children");

    cout << "curr=" << curr->dump() << std::endl; // { B: ... } OK
    cout << "data=" << data.dump() << std::endl; // { A: ... } OK

Is there a better way to work with json in this way?

@gregmarr
Copy link
Contributor

gregmarr commented Jul 5, 2016

Since curr is a reference to data, it is by definition identical to data. This includes that any change made to it applies to data. That is not specific to this library in any way. It is just how C++ works. What you wrote is identical to this code:

int main() {
    string text = "{\"A\":{\"id\":1,\"children\":{\"B\":{\"id\":2,\"children\":{\"C\":{\"id\":3,\"children\":{}}}}}}}";
    json data = json::parse(text);

    data = data["A"]["children"];

    cout << "data=" << data.dump() << std::endl; // { B: ... } OK
    cout << "data=" << data.dump() << std::endl; // { B: ... }
}

@froatsnook
Copy link
Author

Hey @gregmarr

I see. I just wonder if there's another way to do it without making a copy of the data?

@nlohmann
Copy link
Owner

nlohmann commented Jul 5, 2016

The library cannot store references or pointers at this point, but will always make a copy of the values to store. It thereby mimics the behavior of the STL containers. Sorry about this.

@gregmarr
Copy link
Contributor

gregmarr commented Jul 6, 2016

You can't rebind references. You need to use a new reference each time, or use something like std::reference_wrapper. http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

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

3 participants