Closed
Labels
release item: ✨ new featuresolution: proposed fixa fix for the issue has been proposed and waits for confirmationa fix for the issue has been proposed and waits for confirmation
Milestone
Description
Usually JSON documents have a meaningful ordering of properties, and rarely it is alphabetical.
With this library all JSON data gets sorted alphabetically, which is undesirable.
I guess it must be due to use of std::map.
Please describe the steps to reproduce the issue.
#include <iostream>
#include "json.hpp"
using Json = nlohmann::json;
int main() {
std::cout << ">>> " << Json{{"C",1},{"B",2},{"A",3}}.dump() << std::endl;
}
What is the expected behavior?
>>> {"C":1, "B":2, "A":3}
And what is the actual behavior instead?
{"A":3,"B":2,"C":1}
Which compiler and operating system are you using?
- Compiler: clang-7 and gcc-7
- Operating system: Ubuntu 18
Which version of the library did you use?
- [ x ] latest release version 3.7.3
Metadata
Metadata
Assignees
Labels
release item: ✨ new featuresolution: proposed fixa fix for the issue has been proposed and waits for confirmationa fix for the issue has been proposed and waits for confirmation
Activity
nlohmann commentedon Jun 8, 2020
This behavior is described in the readme including ways to circumvent it.
gatopeich commentedon Jun 8, 2020
Thanks, I had missed the Order of object keys section in README.
Great library BTW.
gatopeich commentedon Jun 8, 2020
I just want to highlight that some
unordered_mapexample in the README does not seem to work:This produces exactly the same as the default:
nlohmann commentedon Jun 8, 2020
The README does not mention using
std::unordered_mapas workaround, buttsl::unordered_mapornlohmann::fifo_map, see https://github.com/nlohmann/json/blob/develop/README.md#order-of-object-keys.gatopeich commentedon Jun 10, 2020
Sure though the commented output under
std::unordered_mapabove is misguiding. I suggest correcting it to highlight the actual order.To preserve insertion order in my use case, I made a minimal solution based on
std::vector.Leaving it here for those who for any reason don't want to import further non-standard dependencies, or want a starting point to build their own:
Again, thanks for this great JSON library!
nlohmann commentedon Jun 10, 2020
Your
VecMapcontainer is very nice and compact. Can I use this as example in the documentation?gatopeich commentedon Jun 10, 2020
Of course 👍
gatopeich commentedon Jun 10, 2020
It works well in my tests.
It is an effective choice for small objects due to the low overhead of
std::vector. And its algorithmic simplicity makes it a good target for compiler optimization.gatopeich commentedon Jun 10, 2020
It was missing
using mapped_type = Tto be fully recognized. Just added it and updated the above comments...nlohmann commentedon Jun 19, 2020
@gatopeich
I am currently trying to put this all together to add this as
ordered_jsonto the library. While writing tests, I saw that removing elements is not yet working. This is my current approach:which fails due to an error in
it = Container::erase(it);:Any ideas? Here is the current state: 4fd0d02
16 remaining items
gatopeich commentedon Jun 21, 2020
The problem is in the definition of
object_tthere is an assumption that the allocator is for aconst string:And a
const stringmay have a specialized implementation, e.g. with smaller allocation requirements, thus with incompatible allocator...nlohmann commentedon Jun 22, 2020
I took the default template arguments from
std::map:I'm afraid changing this would break the API. Any idea how to fix the "vector of pairs" approach? Maybe using two vectors?
gatopeich commentedon Jun 22, 2020
I see 3 ways forward:
AllocatorType<Container::value_type>inside the declaration ofobject_t. Note thatContainer::value_type==object_t::value_type==basic_json::value_typeso it is a self-referencing template... Seems beyond my template abilities, but it would clear the way to any Container class, not just std::vector.Probably the cleanest way is by wrapping std::map:
then ObjectType = MapWrapper, and
object_tdeclaration would be much simpler:Only I would not want to go into mayor refactoring 🙂 so...
Re-implement
vector::erase() without relying on pair move operationsmissing due to const member. e.g. by using in-place destructor + constructor. I am working at this now.Use
std::forward_listinstead ofstd::vector. Me not like it, but should work.gatopeich commentedon Jul 6, 2020
Hey @nlohmann my pull request #2206 is ready and waiting...
gatopeich commentedon Jul 17, 2020
Thanks for taking this in!
shdxiang commentedon Dec 11, 2020
great feature @gatopeich
pkbehera commentedon Oct 27, 2022
@nlohmann I think this should have been named
unordered_json, in-line with whatstd::map,std::unordered_map,std::set,std::unordered_setdo.std::maporders its elements in a particular fashion, whilestd::unordered_mappreserves the order in which its elements are inserted. Sostd::mapis actually an alias forordered_mapSimilarly
nhlomann::jsonshould have been alias forordered_jsonas implicitly sorts the elements andnhlomann::unordered_jsonshould preserve the order of insertion (i.e. it does not sort). 😄nlohmann commentedon Oct 27, 2022
This is not true. In
std::unordered_map, elements are hashed and stored in buckets.See https://json.nlohmann.me/features/object_order/ on the rationale.