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

[Feature request] Access by path #1053

Closed
SylvainCorlay opened this issue Apr 13, 2018 · 19 comments
Closed

[Feature request] Access by path #1053

SylvainCorlay opened this issue Apr 13, 2018 · 19 comments
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@SylvainCorlay
Copy link

It would be great if there was accessors by path in a JSON object:

for example, if we have a JSON object x containing

{
    "foo": {
        "bar": {
            "value": 1   
        },
        "baz": {
            "value": 3
        }
    }
}

x[{"foo", "baz"}] would return a JSON object containing

{
    "value": 3
}
@SylvainCorlay
Copy link
Author

cc @martinRenou

@nlohmann
Copy link
Owner

What is the difference to x["foo"]["baz"]?

@SylvainCorlay
Copy link
Author

SylvainCorlay commented Apr 13, 2018

What is the difference to x["foo"]["baz"]?

The difference is the unknown number of elements in the sequence.

I guess that we could have an API based on iterator pairs for the sequence, and have the initializer list and container-based version rebind to it.

@SylvainCorlay
Copy link
Author

What about an accessor with an iterator pair

JSON.at(first, last)

although the value type for the iterator should be a string / integral, or a variant containing string or some integral type. I guess it is not that simple.

@theodelrieu
Copy link
Contributor

Isn't json_pointer what you're looking for?

@nlohmann
Copy link
Owner

@theodelrieu is right. JSON Pointers can do this:

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main()
{
    json j = R"({
        "foo": {
            "bar": {
                "value": 1
            },
            "baz": {
                "value": 3
            }
        }
    })"_json;

    std::cout << j["/foo/baz"_json_pointer] << std::endl;
}

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Apr 13, 2018
@SylvainCorlay
Copy link
Author

Thanks! I did not know about this!

@juzzlin
Copy link

juzzlin commented May 19, 2021

Stupid question, but how do you use _json_pointer with a string variable instead of a literal?

@sentiment-bot
Copy link

sentiment-bot bot commented May 19, 2021

Please be sure to review the code of conduct and be respectful of other users. cc/ @nlohmann
Keep in mind, this repository uses the Contributor Covenant.

@nlohmann
Copy link
Owner

json_pointer is also a class. You can pass a string to create a JSON Pointer.

@juzzlin
Copy link

juzzlin commented May 19, 2021

Could you give an example?

I'm trying to do something like this, but I don't understand why it won't compile:

using nlohmann::json;
using nlohmann::json_pointer;

json root;
std::string path = "/foo/bar";
root[json_pointer(path)] = 42;

@nlohmann
Copy link
Owner

What is the compiler error?

@juzzlin
Copy link

juzzlin commented May 19, 2021

This is the first one:

test.cpp:18:25: error: class template argument deduction failed:
   root[json_pointer(path)] = 42;
                         ^

Also:

json.hpp:10459:14: note: candidate: template<class BasicJsonType> json_pointer(const string&)-> nlohmann::json_pointer<BasicJsonType>
     explicit json_pointer(const std::string& s = "")
              ^~~~~~~~~~~~

@juzzlin
Copy link

juzzlin commented May 19, 2021

Seems that it just had to be root[json_pointer<std::string>(...). Thanks a lot!

@anirudh582
Copy link

#include <iostream>
#include "json.hpp"

using json = nlohmann::ordered_json;

int main()
{
    json j = R"({
        "foo": {
            "bar": {
                "value": 1
            },
            "baz": {
                "value": 3
            }
        }
    })"_json;

    std::cout << j["/foo/baz"_json_pointer] << std::endl;
}

This code prints null. The only difference here is I am using ordered_json instead of json. Is there a way to make this work for ordered_json? Thanks.

@falbrechtskirchinger
Copy link
Contributor

@anirudh582 Works fine here: https://godbolt.org/z/ExaTeeMTd

What version/compiler are you using?

@anirudh582
Copy link

I am using version 3.10.5. I checked with the latest version and it is working. Thank you!

@falbrechtskirchinger
Copy link
Contributor

I am using version 3.10.5. I checked with the latest version and it is working. Thank you!

j[json::json_pointer("/foo/baz")] should work in 3.10.5. Due to a bug, your code is equivalent to: j["/foo/baz"] (i.e., the json_pointer is converted to string)

@anirudh582
Copy link

j[json::json_pointer("/foo/baz")] should work in 3.10.5. Due to a bug, your code is equivalent to: j["/foo/baz"] (i.e., the json_pointer is converted to string)

I checked this and j[json::json_pointer("/foo/baz")] does indeed work in 3.10.5. Thank you very much!

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

No branches or pull requests

6 participants