Skip to content

Commit 4fd0d02

Browse files
committed
🚧 toward an ordered_json type
1 parent e7452d8 commit 4fd0d02

File tree

6 files changed

+211
-0
lines changed

6 files changed

+211
-0
lines changed

include/nlohmann/json.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ SOFTWARE.
7272
#include <nlohmann/detail/output/serializer.hpp>
7373
#include <nlohmann/detail/value_t.hpp>
7474
#include <nlohmann/json_fwd.hpp>
75+
#include <nlohmann/ordered_map.hpp>
7576

7677
/*!
7778
@brief namespace for Niels Lohmann

include/nlohmann/json_fwd.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ uses the standard template types.
6060
@since version 1.0.0
6161
*/
6262
using json = basic_json<>;
63+
64+
template<class Key, class T, class IgnoredLess, class Allocator, class Container>
65+
struct ordered_map;
66+
67+
/*!
68+
@brief ordered JSON class
69+
70+
This type preserves the insertion order of object keys.
71+
72+
@since version 3.9.0
73+
*/
74+
using ordered_json = basic_json<nlohmann::ordered_map>;
75+
6376
} // namespace nlohmann
6477

6578
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

include/nlohmann/ordered_map.hpp

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#pragma once
2+
3+
#include <functional> // less
4+
#include <memory> // allocator
5+
#include <utility> // pair
6+
#include <vector> // vector
7+
8+
namespace nlohmann
9+
{
10+
11+
/// ordered_map: a minimal map-like container that preserves insertion order
12+
/// for use within nlohmann::basic_json<ordered_map>
13+
template<class Key, class T, class IgnoredLess = std::less<Key>,
14+
class Allocator = std::allocator<std::pair<const Key, T>>,
15+
class Container = std::vector<std::pair<const Key, T>, Allocator>>
16+
struct ordered_map : Container
17+
{
18+
using key_type = Key;
19+
using mapped_type = T;
20+
using value_type = std::pair<const Key, T>;
21+
using Container::Container;
22+
23+
std::pair<typename Container::iterator, bool> emplace(key_type&& key, T&& t)
24+
{
25+
for (auto it = this->begin(); it != this->end(); ++it)
26+
{
27+
if (it->first == key)
28+
{
29+
return {it, false};
30+
}
31+
}
32+
33+
this->emplace_back(key, t);
34+
return {--this->end(), true};
35+
}
36+
37+
std::size_t erase(const key_type& key)
38+
{
39+
std::size_t result = 0;
40+
for (auto it = this->begin(); it != this->end();)
41+
{
42+
if (it->first == key)
43+
{
44+
++result;
45+
it = Container::erase(it);
46+
}
47+
else
48+
{
49+
++it;
50+
}
51+
}
52+
53+
return result;
54+
}
55+
56+
T& operator[](key_type&& key)
57+
{
58+
return emplace(std::move(key), T{}).first->second;
59+
}
60+
};
61+
62+
} // namespace nlohmann

single_include/nlohmann/json.hpp

+73
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,15 @@ uses the standard template types.
27722772
@since version 1.0.0
27732773
*/
27742774
using json = basic_json<>;
2775+
2776+
template<class Key, class T, class IgnoredLess, class Allocator, class Container>
2777+
struct ordered_map;
2778+
2779+
/*!
2780+
@since version 3.9.0
2781+
*/
2782+
using ordered_json = basic_json<nlohmann::ordered_map>;
2783+
27752784
} // namespace nlohmann
27762785

27772786
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
@@ -15853,6 +15862,70 @@ class serializer
1585315862

1585415863
// #include <nlohmann/json_fwd.hpp>
1585515864

15865+
// #include <nlohmann/ordered_map.hpp>
15866+
15867+
15868+
#include <functional> // less
15869+
#include <memory> // allocator
15870+
#include <utility> // pair
15871+
#include <vector> // vector
15872+
15873+
namespace nlohmann
15874+
{
15875+
15876+
/// ordered_map: a minimal map-like container that preserves insertion order
15877+
/// for use within nlohmann::basic_json<ordered_map>
15878+
template<class Key, class T, class IgnoredLess = std::less<Key>,
15879+
class Allocator = std::allocator<std::pair<const Key, T>>,
15880+
class Container = std::vector<std::pair<const Key, T>, Allocator>>
15881+
struct ordered_map : Container
15882+
{
15883+
using key_type = Key;
15884+
using mapped_type = T;
15885+
using value_type = std::pair<const Key, T>;
15886+
using Container::Container;
15887+
15888+
std::pair<typename Container::iterator, bool> emplace(Key&& key, T&& t)
15889+
{
15890+
for (auto it = this->begin(); it != this->end(); ++it)
15891+
{
15892+
if (it->first == key)
15893+
{
15894+
return {it, false};
15895+
}
15896+
}
15897+
15898+
this->emplace_back(key, t);
15899+
return {--this->end(), true};
15900+
}
15901+
15902+
std::size_t erase(const Key& key)
15903+
{
15904+
std::size_t result = 0;
15905+
for (auto it = this->begin(); it != this->end(); )
15906+
{
15907+
if (it->first == key)
15908+
{
15909+
++result;
15910+
it = Container::erase(it);
15911+
}
15912+
else
15913+
{
15914+
++it;
15915+
}
15916+
}
15917+
15918+
return result;
15919+
}
15920+
15921+
T& operator[]( Key&& key )
15922+
{
15923+
return emplace(std::move(key), T{}).first->second;
15924+
}
15925+
};
15926+
15927+
} // namespace nlohmann
15928+
1585615929

1585715930
/*!
1585815931
@brief namespace for Niels Lohmann

test/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ set(files
123123
src/unit-modifiers.cpp
124124
src/unit-msgpack.cpp
125125
src/unit-noexcept.cpp
126+
src/unit-ordered_json.cpp
126127
src/unit-pointer_access.cpp
127128
src/unit-readme.cpp
128129
src/unit-reference_access.cpp

test/src/unit-ordered_json.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
__ _____ _____ _____
3+
__| | __| | | | JSON for Modern C++ (test suite)
4+
| | |__ | | | | | | version 3.8.0
5+
|_____|_____|_____|_|___| https://github.com/nlohmann/json
6+
7+
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8+
SPDX-License-Identifier: MIT
9+
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10+
11+
Permission is hereby granted, free of charge, to any person obtaining a copy
12+
of this software and associated documentation files (the "Software"), to deal
13+
in the Software without restriction, including without limitation the rights
14+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
copies of the Software, and to permit persons to whom the Software is
16+
furnished to do so, subject to the following conditions:
17+
18+
The above copyright notice and this permission notice shall be included in all
19+
copies or substantial portions of the Software.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
SOFTWARE.
28+
*/
29+
30+
#include "doctest_compatibility.h"
31+
32+
#include <nlohmann/json.hpp>
33+
using nlohmann::json;
34+
using nlohmann::ordered_json;
35+
36+
37+
TEST_CASE("ordered_json")
38+
{
39+
json j;
40+
ordered_json oj;
41+
42+
j["element3"] = 3;
43+
j["element1"] = 1;
44+
j["element2"] = 2;
45+
46+
oj["element3"] = 3;
47+
oj["element1"] = 1;
48+
oj["element2"] = 2;
49+
50+
CHECK(j.dump() == "{\"element1\":1,\"element2\":2,\"element3\":3}");
51+
CHECK(oj.dump() == "{\"element3\":3,\"element1\":1,\"element2\":2}");
52+
53+
CHECK(j == json(oj));
54+
CHECK(ordered_json(json(oj)) == ordered_json(j));
55+
56+
j.erase("element1");
57+
oj.erase("element1");
58+
59+
CHECK(j.dump() == "{\"element2\":2,\"element3\":3}");
60+
CHECK(oj.dump() == "{\"element3\":3,\"element2\":2}");
61+
}

0 commit comments

Comments
 (0)