nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
43.15k stars 6.73k forks source link

Docs - What does Json[key] return? #267

Closed MartinNvp closed 8 years ago

MartinNvp commented 8 years ago

Background

I wanted to loop through the keys of "instruments" (without assuming the nature of the contained values).

{
  "instruments": {
    "cu1608": {"MaxPos": 3, "StartTime": "09:00" },
    "cu1609": {"MaxPos": 0, "StartTime": "09:00" },
    "cu1610": {"MaxPos": 0, "StartTime": "09:00" },
  }
}

Your main readme.md is great, but seems a tad more focus on loading than reading/querying Json. (The forms of loading are impressive/elegant.) All the examples I could find for iterating over JSON object/map content where at the top level. Not nested.

I wanted to know what the operator[] returned. I dug into the class docs. Found json::operator[] returned some reference type. Which did not look iterable.

Despite that observation (is it wrong?) this code works:

void strathost_from_json(StrategyHostParams& host, const json& j)
    {
        host.subscribe_instrumentname_list.clear();
        const json& instrums = j["instruments"]; //<<<< this bit was hard to figure out
        for (json::const_iterator it = instrums.begin(); it != instrums.end(); ++it)
            host.subscribe_instrumentname_list.emplace_back(it.key());
    }

So I can get a JSON object at every level all the way down. Happy Surprise.

Request

Can (or should?) that readme.md docs state something like:

(Hope this aint daft, new to use of your JSON, or any JSON actually.)

nlohmann commented 8 years ago

Hi @MartinNvp, there is a documentation beyond the README file. It's not great (see #248), but it contains a page for operator[]. The return value is a reference (or const reference, when applied to a const variable, just like the similar function for std::map).

To your questions:

  1. By definition of JSON, an object is a key/value pair where the value can again be any JSON type. The implementation follows this approach and uses a recursive definition. Therefore, the nlohmann::basic_json::value_type is again nlohmann::basic_json (see https://nlohmann.github.io/json/classnlohmann_1_1basic__json_ac8d45b57874b4a6e9c07f7d3b5daa1f9.html#ac8d45b57874b4a6e9c07f7d3b5daa1f9).
  2. nlohmann::basic_json::operator[] returns either reference or const_reference, which are aliases for nlohmann::basic_json& or const nlohmann::basic_json&, respectively.
  3. Can you propose an example that could extend those of https://github.com/nlohmann/json#stl-like-access?
MartinNvp commented 8 years ago

Yes I had read the operator[] docs. And then clicked through into the Reference type. which was in turn defined as value_t. I had assumed that was may be a variant of simpler types like int/string/array/map...

The recursive definition is cool (may be obvious) but too implicit for my head ;-)

I'll take a look at extending your example.

But can we state that recursive deinition on the main readme.md?

nlohmann commented 8 years ago

In fact, value_t and value_type are different types. The name value_type is used in Containers to refer to the contained value type, so int in case of std::vector<int>, and reference is typically defined as value_type&.

I think as you confused value_t (a plain enum) and value_type&, you did not expect recursive access.

MartinNvp commented 8 years ago

Yes it is as you say, but too subtle for a man in a rush!

MartinNvp commented 8 years ago

An example like this would have helped me the most:

auto j_all = 
R"( {                                               )"
R"( "Pets":                                         )"
R"(     {                                           )"
R"(     "Cats":                                     )"
R"(         {"Lions":3, "Tigers":5},                )"
R"(     "Dogs":                                     )"
R"(         {"Terrier":1, "Afgan":0, "Alsation":2}  )"
R"(     }                                           )"
R"( }                                               )"_json;

// Its json objects all the way down:
json j_pets = j_all["pets"];    
json j_cats = j_pets["cats"];
json j_lions = j_cats["Lions"];
// or equivalently:
json j_lions2 =j_all["Pets"]["Cats"]["Lions"];
nlohmann commented 8 years ago

I don't think that such a hint is useful for many others. Nevertheless, I shall try to improve the presentation of the documentation.

MartinNvp commented 8 years ago

up to you. Any simple statement that json[] returns json would be helpful.