-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
Key iterator #46
Comments
The problem with giving access to the key is that not all json objects are composed of key-value pairs. For example, an array is a valid json object but has no keys other than its indices. I have been able to successfully retrieve the keys for a json object by copying the object to a string to object map and iterating through that, though I agree that a more comprehensive solution is necessary. |
By string to object map I mean string to json object. |
The following is a valid json object: When iterating over it we get: I would like to somehow be able to get the keys of these objects: The easiest solution I can think of is for every json object to have a Since you cannot really search the parent object, an alternative more memory-friendly solution is to provide a key-value pair iterator that throws when your object is an array (in the same way that |
Do you mean Like this: nlohmann::json j
= {{"b", {{"c", 2}, {"d", 3}}}, {"d", {{"c", 2}, {"d", 3}}}};
std::map<std::string, nlohmann::json> m = j;
for (auto&& kv : m) {
std::cout << kv.first << std::endl;
} ? |
The key method used to be part of the iterator class but was recently deprecated. This problem of getting the key is part of a much larger problem, namely that json isn't statically typed but C++ is. This issue is cannot be resolved through inheritance because each type implements a different interface. The best solution I can think of is to allow the user to cast the iterator to a pair and throw an exception if that is invalid. |
Right now We need an iterator that only works on That is, the interface would provide two iterators: one for arrays (return just values), one for object sequences (return key value pairs). If the previous interface was mixing both into one then I agree that that is a bad idea. You could return something like key-value pair where the key is a variant, and a json object using key = variant<string, int>;
using value_type = std::pair<key, json>;
for (auto&& kv : json_sequence) {
auto key = kv.first;
auto value = kv.second;
json_sequence[key] = ...;
}
json operator[](variant<string, int> v) {
switch(v.which) {
case integer: { ... }
case string: { ... }
}
} but it is a complex solution. |
Yes |
Eventually, the user needs to decide whether the iterator refers to a key and value or to a key alone. Therefore, I'm suggesting something much simpler to resolve the issue. Consider this example from the readme: json j = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"answer", {
{"everything", 42}
}},
{"list", {1, 0, 2}},
{"object", {
{"currency", "USD"},
{"value", 42.99}
}}
}; Here is my solution: auto it1 = j.find("pi");
// it1 is internally represented as a map iterator
auto pair1 = static_cast<PairIter>(it1);
auto it2 = j["list"].begin();
// it2 is internally represented as a vector iterator
auto pair2 = static_cast<PairIter>(it2);
// the above should throw an exception |
@isaach1000 How would you use that with range-based for? |
Okay that is a good point. How about just having the json object return a pair iterator if it is an object, but a vector iterator if the it is an array? |
Hi there, an earlier version of the library had There are several ways I can think of approaching the issue:
What do you think, @isaach1000, @gnzlbg? |
You can have your own reverse iterator that inherits from On Tue, Mar 24, 2015 at 5:48 PM, Niels notifications@github.com wrote:
|
Very good point! I'll check... |
Currently only support iterator and const_iterator. reverse_iterator and const_reverse_iterator to be implemented soon.
I added a class reverse_foo : public std::reverse_iterator<basic_json::iterator>
{
public:
inline typename object_t::key_type key() const
{
return base().key();
}
inline reference value() const
{
return base().operator*();
}
}; but it seems as if |
Have you tried On Tue, Mar 24, 2015 at 7:53 PM, Niels notifications@github.com wrote:
|
With some hindsight now I think that creating your own reverse iterator is That might be problematic when writing generic code, but it is also pretty On Tue, Mar 24, 2015 at 9:43 PM, Gonzalo BG gonzalobg88@gmail.com wrote:
|
With |
All iterators have now member functions |
Thanks, i'll give it a try :) |
When iterating over a
json
object, e.g. using a range-based for loop, one only gets the values, and it is impossible right now to get the key of each value. It would be nice to be able to iterate over the keys, since this allows you to get the value afterwards if you want too.Another alternative is a key.value pair iterator like map.
The text was updated successfully, but these errors were encountered: