-
-
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
Request: range-based-for over a json-object to expose .first/.second #350
Comments
I did not find a way to realize this without any syntactic adjustment, but you can do this: json j = {{"A", 1}, {"B", 2}};
for (auto i : json::iterator_wrapper(j))
{
auto x = i.key(); // x = "A", x = "B"
auto y = i.value(); // y = 1, y = 2
} See https://github.com/nlohmann/json/blob/develop/test/src/unit-iterator_wrapper.cpp for more examples. If you have any idea to realize this without a wrapper, please let me know! |
I think it will require:
Personally, I really dont like the key/value functions and would rather just use first/second ... and this is the minimal approach I can think of. What do you think? I'm happy to start working on a patch, but if you think it's a non-starter, then I'll skip it. |
So basically the syntax of the loop would be the same, but you'd rather write |
My goal is to make range-for over a json-object easy, which really doesnt work right now (well without your "iterator_wrapper" suggestion, which is not very discoverable). I personally prefer .first/.second because I want it to feel like a map, but that's bikeshedding. Honestly, none of these sound like awesome solutions. Another option is to use get_ref to get the internal STL map object, but that's even worse to type. |
So again - if there would be a better name for the |
Any opinions on this? |
I once again shall try to get another opinion on how to name the |
make_iterator(json&)? |
make_object_iterator(json&)? |
I'm still not too happy about the namings. In any case, does adding |
I would rather have a member function than a free function for sake of reading and typing. Something like |
The aliases could be added easily. Member variables with key and value aka /*!
@copydoc iterator_wrapper(reference)
*/
static iteration_proxy<iterator> range(reference cont)
{
return iteration_proxy<iterator>(cont);
}
/*!
@copydoc iterator_wrapper(reference)
*/
static iteration_proxy<const_iterator> range(const_reference cont)
{
return iteration_proxy<const_iterator>(cont);
}
/*!
@copydoc iterator_wrapper(reference)
*/
iteration_proxy<iterator> range()
{
return iteration_proxy<iterator>(*this);
}
/*!
@copydoc iterator_wrapper(reference)
*/
iteration_proxy<const_iterator> range() const
{
return iteration_proxy<const_iterator>(*this);
} |
The Any help is greatly appreciated! |
That solution makes you pay the copy cost of the key string even if you were just going to call .key(), which wouldn't use it. I think I know a better way. I'll make a PR for it. |
I need to update the documentation, so I reopened the issue. |
There is still an issue in the code, see #578. |
The test cases succeed now, but only because they just use Consider this example: #include "json.hpp"
using json = nlohmann::json;
int main()
{
json j_object = {{"one", 1}, {"two", 2}};
for (auto& x : json::iterator_wrapper(j_object))
{
std::cout << "key: " << x.first << ", value: " << x.second << '\n';
}
} It does not compile with Clang or GCC:
I would like to be able to have |
Maybe we should take it out. It's strange that the implicit conversion works for some, but not all compilers. |
I reverted the last PRs. It seems we need a new idea or we need to close this as "won't fix". |
I'm having a change of heart on this one. I think "won't fix" is the right course of action. Using .key() and .value() vs .first and .second indicate better that something is being done to fetch what you requested. There could be a conversion to std::pair<key_type, value_type>, which might let you write something like
, but it would require you to use an explicit std::pair type. Note also that it's a value type, not a reference, so you're paying a copy cost. I think just using .key() and .value() may be best. |
I would love to have the ability to iterate over a JSON object type in exactly the same way I would iterate over a std::map:
for(auto& i : map) { i.first; i.second; }
Would it be possible to have a free function (or member) that would allow me to do something like:
for(auto& i : as_map(jsonObj)) {...}
such that the iterator exposed here works more like map::iterator (.first,.second) than the current iterator type (.key,.value).
The text was updated successfully, but these errors were encountered: