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

Periods/literal dots in keys? #1338

Closed
alfaunits opened this issue Nov 7, 2018 · 13 comments
Closed

Periods/literal dots in keys? #1338

alfaunits opened this issue Nov 7, 2018 · 13 comments

Comments

@alfaunits
Copy link

Hi. Please forgive if this is a silly question, I am new to JSON handling.

I am trying to access a value, with key.key2 combo, which I believe is a valid as per JSON specs?
e.g.
{
Level1: { Level2: Something}
}
In other libs, I could do json["Level1.Level2"] to get "Something". I can do json["Level1"]["Level2"] with nlohmann lib, but not the access with a period.

The keys do not have periods, rather, this should be a "subkey", right?

@nlohmann
Copy link
Owner

nlohmann commented Nov 7, 2018

The period notation is not JSON. In JSON, a key is just a string:

There is no special syntax to shortcut the access to nested objects.

@alfaunits
Copy link
Author

Uhh, bad :( Gotta make an API to work around that then.
Thanks.

@OvermindDL1
Copy link

@alfaunits How would such a feature work anyway? A key can contain a period, wouldn't such a subscript access method break things?

@alfaunits
Copy link
Author

I've seen a lot of questions on the net about how to use a period in a key, where the answer was it is not supported as it is a special character.

I am changing existing code, not of my making, which uses periods (or literal dots, frankly, I do not know if there is a difference ;)), as noted above.

Currently, it is only a key.subkey combo, so I just added a second parameter to the call instead (["key"]["subkey"] instead of ["key"]), but if there are more than one sublevels, I'd need to add variable parameter count functions.

@gregmarr
Copy link
Contributor

gregmarr commented Nov 7, 2018

Maybe using a json path here would be easier? I haven't done it myself, but I've seen others doing it, and I know it uses slashes instead of dots.

@OvermindDL1
Copy link

I've seen a lot of questions on the net about how to use a period in a key, where the answer was it is not supported as it is a special character.

It is absolutely not a special character according to the JSON spec. Here, from the javascript console in this window itself:

> let somejson = '{"blah.blorp": 42, "blah": {"blorp": 6.28}}'
undefined
> let parsed = JSON.parse(somejson)
undefined
> parsed["blah.blorp"]
42
> parsed["blah"]["blorp"]
6.28

Currently, it is only a key.subkey combo, so I just added a second parameter to the call instead (["key"]["subkey"] instead of ["key"]), but if there are more than one sublevels, I'd need to add variable parameter count functions.

Or just reduce down the list of keys, significantly easier.

Maybe using a json path here would be easier? I haven't done it myself, but I've seen others doing it, and I know it uses slashes instead of dots.

Again, from the javascript console here right now:

> let somejson1 = '{"blah/blorp": 42, "blah": {"blorp": 6.28}}'
undefined
> let parsed1 = JSON.parse(somejson1)
undefined
> parsed1["blah/blorp"]
42
> parsed1["blah"]["blorp"]
6.28

Keys by the JSON spec are allowed to contain ANY character that JSON can encode as a string as they are just strings. Thus using a 'special character' in a string as some kind of separator will always fail in some cases, thus encode the path a different way, like a list/array of strings that you can then trivially reduce on.

@alfaunits
Copy link
Author

[quote]Maybe using a json path here would be easier? I haven't done it myself, but I've seen others doing it, and I know it uses slashes instead of dots.[/quote]
Oh, so json["key\subkey"] is OK in nlohmann's lib?

@gregmarr
Copy link
Contributor

gregmarr commented Nov 7, 2018

@alfaunits
Copy link
Author

That seems like a lot more code to achieve what was a one-liner.
Thanks :)

@alfaunits
Copy link
Author

To trail on this, and so as not to open another topic..

Is there any "cleaner" way to do something like json["key"]["subkey"] without exceptions being thrown if either key/subkey do not exist?
So far all I could find is if(json.find("key") != json.end() && json["key"].find("subkey") != json["key"].end()) return json["key"]["subkey"]

json.value won't work here.

@OvermindDL1
Copy link

Could just make a wrapper function to 'extract' like auto result = extract(json, {"key", "subkey"}); or so. I could see such a function being added to this library as useful. :-)

The implementation of it could be a trivial auto end = std::end(keys);auto it = std::begin(keys);while(end!=it){if(json.find(*it)) json=json[*it] else return std::optional();};return std::optional(json); or so (properly formatted of course).

@alfaunits
Copy link
Author

This is simply a matter of readability. I did make such a warpper for the time being :)

@nlohmann
Copy link
Owner

nlohmann commented Nov 9, 2018

I think this use case is rather special and nothing the library's API should offer. However, you can realize it with client code, so there is no need to change the API.

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

4 participants