1//     __ _____ _____ _____
2//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3// |  |  |__   |  |  | | | |  version 3.11.2
4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5//
6// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
7// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8// SPDX-License-Identifier: MIT
9
10#include "doctest_compatibility.h"
11
12#include <nlohmann/json.hpp>
13#ifdef JSON_TEST_NO_GLOBAL_UDLS
14    using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
15#endif
16
17// build test with C++14
18// JSON_HAS_CPP_14
19
20TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json)
21{
22    SECTION("object")
23    {
24        Json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", Json::object()}, {"array", {1, 2, 3}}};
25        const Json j_const = j;
26
27        SECTION("access specified element with bounds checking")
28        {
29            SECTION("access within bounds")
30            {
31                CHECK(j.at("integer") == Json(1));
32                CHECK(j.at("unsigned") == Json(1u));
33                CHECK(j.at("boolean") == Json(true));
34                CHECK(j.at("null") == Json(nullptr));
35                CHECK(j.at("string") == Json("hello world"));
36                CHECK(j.at("floating") == Json(42.23));
37                CHECK(j.at("object") == Json::object());
38                CHECK(j.at("array") == Json({1, 2, 3}));
39
40                CHECK(j_const.at("integer") == Json(1));
41                CHECK(j_const.at("unsigned") == Json(1u));
42                CHECK(j_const.at("boolean") == Json(true));
43                CHECK(j_const.at("null") == Json(nullptr));
44                CHECK(j_const.at("string") == Json("hello world"));
45                CHECK(j_const.at("floating") == Json(42.23));
46                CHECK(j_const.at("object") == Json::object());
47                CHECK(j_const.at("array") == Json({1, 2, 3}));
48
49#ifdef JSON_HAS_CPP_17
50                CHECK(j.at(std::string_view("integer")) == Json(1));
51                CHECK(j.at(std::string_view("unsigned")) == Json(1u));
52                CHECK(j.at(std::string_view("boolean")) == Json(true));
53                CHECK(j.at(std::string_view("null")) == Json(nullptr));
54                CHECK(j.at(std::string_view("string")) == Json("hello world"));
55                CHECK(j.at(std::string_view("floating")) == Json(42.23));
56                CHECK(j.at(std::string_view("object")) == Json::object());
57                CHECK(j.at(std::string_view("array")) == Json({1, 2, 3}));
58
59                CHECK(j_const.at(std::string_view("integer")) == Json(1));
60                CHECK(j_const.at(std::string_view("unsigned")) == Json(1u));
61                CHECK(j_const.at(std::string_view("boolean")) == Json(true));
62                CHECK(j_const.at(std::string_view("null")) == Json(nullptr));
63                CHECK(j_const.at(std::string_view("string")) == Json("hello world"));
64                CHECK(j_const.at(std::string_view("floating")) == Json(42.23));
65                CHECK(j_const.at(std::string_view("object")) == Json::object());
66                CHECK(j_const.at(std::string_view("array")) == Json({1, 2, 3}));
67#endif
68            }
69
70            SECTION("access outside bounds")
71            {
72                CHECK_THROWS_WITH_AS(j.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found", typename Json::out_of_range&);
73                CHECK_THROWS_WITH_AS(j_const.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found", typename Json::out_of_range&);
74
75
76#ifdef JSON_HAS_CPP_17
77                CHECK_THROWS_WITH_AS(j.at(std::string_view("foo")), "[json.exception.out_of_range.403] key 'foo' not found", typename Json::out_of_range&);
78                CHECK_THROWS_WITH_AS(j_const.at(std::string_view("foo")), "[json.exception.out_of_range.403] key 'foo' not found", typename Json::out_of_range&);
79#endif
80            }
81
82            SECTION("access on non-object type")
83            {
84                SECTION("null")
85                {
86                    Json j_nonobject(Json::value_t::null);
87                    const Json j_nonobject_const(j_nonobject);
88                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&);
89                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&);
90
91#ifdef JSON_HAS_CPP_17
92                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view(std::string_view("foo"))), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&);
93                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view(std::string_view("foo"))), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&);
94#endif
95                }
96
97                SECTION("boolean")
98                {
99                    Json j_nonobject(Json::value_t::boolean);
100                    const Json j_nonobject_const(j_nonobject);
101                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&);
102                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&);
103
104#ifdef JSON_HAS_CPP_17
105                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&);
106                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&);
107#endif
108                }
109
110                SECTION("string")
111                {
112                    Json j_nonobject(Json::value_t::string);
113                    const Json j_nonobject_const(j_nonobject);
114                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&);
115                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&);
116
117#ifdef JSON_HAS_CPP_17
118                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&);
119                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&);
120#endif
121                }
122
123                SECTION("array")
124                {
125                    Json j_nonobject(Json::value_t::array);
126                    const Json j_nonobject_const(j_nonobject);
127                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&);
128                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&);
129
130#ifdef JSON_HAS_CPP_17
131                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&);
132                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&);
133#endif
134                }
135
136                SECTION("number (integer)")
137                {
138                    Json j_nonobject(Json::value_t::number_integer);
139                    const Json j_nonobject_const(j_nonobject);
140                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
141                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
142
143#ifdef JSON_HAS_CPP_17
144                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
145                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
146#endif
147                }
148
149                SECTION("number (unsigned)")
150                {
151                    Json j_nonobject(Json::value_t::number_unsigned);
152                    const Json j_nonobject_const(j_nonobject);
153                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
154                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
155
156#ifdef JSON_HAS_CPP_17
157                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
158                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
159#endif
160                }
161
162                SECTION("number (floating-point)")
163                {
164                    Json j_nonobject(Json::value_t::number_float);
165                    const Json j_nonobject_const(j_nonobject);
166                    CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
167                    CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
168
169#ifdef JSON_HAS_CPP_17
170                    CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
171                    CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&);
172#endif
173                }
174            }
175        }
176
177        SECTION("access specified element with default value")
178        {
179            SECTION("given a key")
180            {
181                SECTION("access existing value")
182                {
183                    CHECK(j.value("integer", 2) == 1);
184                    CHECK(j.value("integer", 1.0) == Approx(1));
185                    CHECK(j.value("unsigned", 2) == 1u);
186                    CHECK(j.value("unsigned", 1.0) == Approx(1u));
187                    CHECK(j.value("null", Json(1)) == Json());
188                    CHECK(j.value("boolean", false) == true);
189                    CHECK(j.value("string", "bar") == "hello world");
190                    CHECK(j.value("string", std::string("bar")) == "hello world");
191                    CHECK(j.value("floating", 12.34) == Approx(42.23));
192                    CHECK(j.value("floating", 12) == 42);
193                    CHECK(j.value("object", Json({{"foo", "bar"}})) == Json::object());
194                    CHECK(j.value("array", Json({10, 100})) == Json({1, 2, 3}));
195
196                    CHECK(j_const.value("integer", 2) == 1);
197                    CHECK(j_const.value("integer", 1.0) == Approx(1));
198                    CHECK(j_const.value("unsigned", 2) == 1u);
199                    CHECK(j_const.value("unsigned", 1.0) == Approx(1u));
200                    CHECK(j_const.value("boolean", false) == true);
201                    CHECK(j_const.value("string", "bar") == "hello world");
202                    CHECK(j_const.value("string", std::string("bar")) == "hello world");
203                    CHECK(j_const.value("floating", 12.34) == Approx(42.23));
204                    CHECK(j_const.value("floating", 12) == 42);
205                    CHECK(j_const.value("object", Json({{"foo", "bar"}})) == Json::object());
206                    CHECK(j_const.value("array", Json({10, 100})) == Json({1, 2, 3}));
207
208#ifdef JSON_HAS_CPP_17
209                    CHECK(j.value(std::string_view("integer"), 2) == 1);
210                    CHECK(j.value(std::string_view("integer"), 1.0) == Approx(1));
211                    CHECK(j.value(std::string_view("unsigned"), 2) == 1u);
212                    CHECK(j.value(std::string_view("unsigned"), 1.0) == Approx(1u));
213                    CHECK(j.value(std::string_view("null"), Json(1)) == Json());
214                    CHECK(j.value(std::string_view("boolean"), false) == true);
215                    CHECK(j.value(std::string_view("string"), "bar") == "hello world");
216                    CHECK(j.value(std::string_view("string"), std::string("bar")) == "hello world");
217                    CHECK(j.value(std::string_view("floating"), 12.34) == Approx(42.23));
218                    CHECK(j.value(std::string_view("floating"), 12) == 42);
219                    CHECK(j.value(std::string_view("object"), Json({{"foo", "bar"}})) == Json::object());
220                    CHECK(j.value(std::string_view("array"), Json({10, 100})) == Json({1, 2, 3}));
221
222                    CHECK(j_const.value(std::string_view("integer"), 2) == 1);
223                    CHECK(j_const.value(std::string_view("integer"), 1.0) == Approx(1));
224                    CHECK(j_const.value(std::string_view("unsigned"), 2) == 1u);
225                    CHECK(j_const.value(std::string_view("unsigned"), 1.0) == Approx(1u));
226                    CHECK(j_const.value(std::string_view("boolean"), false) == true);
227                    CHECK(j_const.value(std::string_view("string"), "bar") == "hello world");
228                    CHECK(j_const.value(std::string_view("string"), std::string("bar")) == "hello world");
229                    CHECK(j_const.value(std::string_view("floating"), 12.34) == Approx(42.23));
230                    CHECK(j_const.value(std::string_view("floating"), 12) == 42);
231                    CHECK(j_const.value(std::string_view("object"), Json({{"foo", "bar"}})) == Json::object());
232                    CHECK(j_const.value(std::string_view("array"), Json({10, 100})) == Json({1, 2, 3}));
233#endif
234                }
235
236                SECTION("access non-existing value")
237                {
238                    CHECK(j.value("_", 2) == 2);
239                    CHECK(j.value("_", 2u) == 2u);
240                    CHECK(j.value("_", false) == false);
241                    CHECK(j.value("_", "bar") == "bar");
242                    CHECK(j.value("_", 12.34) == Approx(12.34));
243                    CHECK(j.value("_", Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
244                    CHECK(j.value("_", Json({10, 100})) == Json({10, 100}));
245
246                    CHECK(j_const.value("_", 2) == 2);
247                    CHECK(j_const.value("_", 2u) == 2u);
248                    CHECK(j_const.value("_", false) == false);
249                    CHECK(j_const.value("_", "bar") == "bar");
250                    CHECK(j_const.value("_", 12.34) == Approx(12.34));
251                    CHECK(j_const.value("_", Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
252                    CHECK(j_const.value("_", Json({10, 100})) == Json({10, 100}));
253
254#ifdef JSON_HAS_CPP_17
255                    CHECK(j.value(std::string_view("_"), 2) == 2);
256                    CHECK(j.value(std::string_view("_"), 2u) == 2u);
257                    CHECK(j.value(std::string_view("_"), false) == false);
258                    CHECK(j.value(std::string_view("_"), "bar") == "bar");
259                    CHECK(j.value(std::string_view("_"), 12.34) == Approx(12.34));
260                    CHECK(j.value(std::string_view("_"), Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
261                    CHECK(j.value(std::string_view("_"), Json({10, 100})) == Json({10, 100}));
262
263                    CHECK(j_const.value(std::string_view("_"), 2) == 2);
264                    CHECK(j_const.value(std::string_view("_"), 2u) == 2u);
265                    CHECK(j_const.value(std::string_view("_"), false) == false);
266                    CHECK(j_const.value(std::string_view("_"), "bar") == "bar");
267                    CHECK(j_const.value(std::string_view("_"), 12.34) == Approx(12.34));
268                    CHECK(j_const.value(std::string_view("_"), Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
269                    CHECK(j_const.value(std::string_view("_"), Json({10, 100})) == Json({10, 100}));
270#endif
271                }
272
273                SECTION("access on non-object type")
274                {
275                    SECTION("null")
276                    {
277                        Json j_nonobject(Json::value_t::null);
278                        const Json j_nonobject_const(Json::value_t::null);
279                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
280                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
281
282#ifdef JSON_HAS_CPP_17
283                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
284                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
285#endif
286                    }
287
288                    SECTION("boolean")
289                    {
290                        Json j_nonobject(Json::value_t::boolean);
291                        const Json j_nonobject_const(Json::value_t::boolean);
292                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
293                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
294
295#ifdef JSON_HAS_CPP_17
296                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
297                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
298#endif
299                    }
300
301                    SECTION("string")
302                    {
303                        Json j_nonobject(Json::value_t::string);
304                        const Json j_nonobject_const(Json::value_t::string);
305                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
306                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
307
308#ifdef JSON_HAS_CPP_17
309                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
310                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
311#endif
312                    }
313
314                    SECTION("array")
315                    {
316                        Json j_nonobject(Json::value_t::array);
317                        const Json j_nonobject_const(Json::value_t::array);
318                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
319                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
320
321#ifdef JSON_HAS_CPP_17
322                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
323                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
324#endif
325                    }
326
327                    SECTION("number (integer)")
328                    {
329                        Json j_nonobject(Json::value_t::number_integer);
330                        const Json j_nonobject_const(Json::value_t::number_integer);
331                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
332                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
333
334#ifdef JSON_HAS_CPP_17
335                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
336                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
337#endif
338                    }
339
340                    SECTION("number (unsigned)")
341                    {
342                        Json j_nonobject(Json::value_t::number_unsigned);
343                        const Json j_nonobject_const(Json::value_t::number_unsigned);
344                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
345                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
346
347#ifdef JSON_HAS_CPP_17
348                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
349                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
350#endif
351                    }
352
353                    SECTION("number (floating-point)")
354                    {
355                        Json j_nonobject(Json::value_t::number_float);
356                        const Json j_nonobject_const(Json::value_t::number_float);
357                        CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
358                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
359
360#ifdef JSON_HAS_CPP_17
361                        CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
362                        CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
363#endif
364                    }
365                }
366            }
367
368            SECTION("given a JSON pointer")
369            {
370                SECTION("access existing value")
371                {
372                    CHECK(j.value("/integer"_json_pointer, 2) == 1);
373                    CHECK(j.value("/integer"_json_pointer, 1.0) == Approx(1));
374                    CHECK(j.value("/unsigned"_json_pointer, 2) == 1u);
375                    CHECK(j.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
376                    CHECK(j.value("/null"_json_pointer, Json(1)) == Json());
377                    CHECK(j.value("/boolean"_json_pointer, false) == true);
378                    CHECK(j.value("/string"_json_pointer, "bar") == "hello world");
379                    CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world");
380                    CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23));
381                    CHECK(j.value("/floating"_json_pointer, 12) == 42);
382                    CHECK(j.value("/object"_json_pointer, Json({{"foo", "bar"}})) == Json::object());
383                    CHECK(j.value("/array"_json_pointer, Json({10, 100})) == Json({1, 2, 3}));
384
385                    CHECK(j_const.value("/integer"_json_pointer, 2) == 1);
386                    CHECK(j_const.value("/integer"_json_pointer, 1.0) == Approx(1));
387                    CHECK(j_const.value("/unsigned"_json_pointer, 2) == 1u);
388                    CHECK(j_const.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
389                    CHECK(j_const.value("/boolean"_json_pointer, false) == true);
390                    CHECK(j_const.value("/string"_json_pointer, "bar") == "hello world");
391                    CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world");
392                    CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23));
393                    CHECK(j_const.value("/floating"_json_pointer, 12) == 42);
394                    CHECK(j_const.value("/object"_json_pointer, Json({{"foo", "bar"}})) == Json::object());
395                    CHECK(j_const.value("/array"_json_pointer, Json({10, 100})) == Json({1, 2, 3}));
396                }
397
398                SECTION("access on non-object type")
399                {
400                    SECTION("null")
401                    {
402                        Json j_nonobject(Json::value_t::null);
403                        const Json j_nonobject_const(Json::value_t::null);
404                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
405                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
406                    }
407
408                    SECTION("boolean")
409                    {
410                        Json j_nonobject(Json::value_t::boolean);
411                        const Json j_nonobject_const(Json::value_t::boolean);
412                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
413                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with boolean", typename Json::type_error&);
414                    }
415
416                    SECTION("string")
417                    {
418                        Json j_nonobject(Json::value_t::string);
419                        const Json j_nonobject_const(Json::value_t::string);
420                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
421                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with string", typename Json::type_error&);
422                    }
423
424                    SECTION("array")
425                    {
426                        Json j_nonobject(Json::value_t::array);
427                        const Json j_nonobject_const(Json::value_t::array);
428                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
429                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
430                    }
431
432                    SECTION("number (integer)")
433                    {
434                        Json j_nonobject(Json::value_t::number_integer);
435                        const Json j_nonobject_const(Json::value_t::number_integer);
436                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
437                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
438                    }
439
440                    SECTION("number (unsigned)")
441                    {
442                        Json j_nonobject(Json::value_t::number_unsigned);
443                        const Json j_nonobject_const(Json::value_t::number_unsigned);
444                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
445                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
446                    }
447
448                    SECTION("number (floating-point)")
449                    {
450                        Json j_nonobject(Json::value_t::number_float);
451                        const Json j_nonobject_const(Json::value_t::number_float);
452                        CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
453                        CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number", typename Json::type_error&);
454                    }
455                }
456            }
457        }
458
459        SECTION("non-const operator[]")
460        {
461            {
462                Json j_null;
463                CHECK(j_null.is_null());
464                j_null["key"] = 1;
465                CHECK(j_null.is_object());
466                CHECK(j_null.size() == 1);
467                j_null["key"] = 2;
468                CHECK(j_null.size() == 1);
469            }
470#ifdef JSON_HAS_CPP_17
471            {
472                std::string_view key = "key";
473                Json j_null;
474                CHECK(j_null.is_null());
475                j_null[key] = 1;
476                CHECK(j_null.is_object());
477                CHECK(j_null.size() == 1);
478                j_null[key] = 2;
479                CHECK(j_null.size() == 1);
480            }
481#endif
482        }
483
484        SECTION("front and back")
485        {
486            if (std::is_same<Json, nlohmann::ordered_json>::value)
487            {
488                // "integer" is the first key
489                CHECK(j.front() == Json(1));
490                CHECK(j_const.front() == Json(1));
491                // "array" is last key
492                CHECK(j.back() == Json({1, 2, 3}));
493                CHECK(j_const.back() == Json({1, 2, 3}));
494            }
495            else
496            {
497                // "array" is the smallest key
498                CHECK(j.front() == Json({1, 2, 3}));
499                CHECK(j_const.front() == Json({1, 2, 3}));
500                // "unsigned" is the largest key
501                CHECK(j.back() == Json(1u));
502                CHECK(j_const.back() == Json(1u));
503            }
504        }
505
506        SECTION("access specified element")
507        {
508            SECTION("access within bounds")
509            {
510                CHECK(j["integer"] == Json(1));
511                CHECK(j[typename Json::object_t::key_type("integer")] == j["integer"]);
512
513                CHECK(j["unsigned"] == Json(1u));
514                CHECK(j[typename Json::object_t::key_type("unsigned")] == j["unsigned"]);
515
516                CHECK(j["boolean"] == Json(true));
517                CHECK(j[typename Json::object_t::key_type("boolean")] == j["boolean"]);
518
519                CHECK(j["null"] == Json(nullptr));
520                CHECK(j[typename Json::object_t::key_type("null")] == j["null"]);
521
522                CHECK(j["string"] == Json("hello world"));
523                CHECK(j[typename Json::object_t::key_type("string")] == j["string"]);
524
525                CHECK(j["floating"] == Json(42.23));
526                CHECK(j[typename Json::object_t::key_type("floating")] == j["floating"]);
527
528                CHECK(j["object"] == Json::object());
529                CHECK(j[typename Json::object_t::key_type("object")] == j["object"]);
530
531                CHECK(j["array"] == Json({1, 2, 3}));
532                CHECK(j[typename Json::object_t::key_type("array")] == j["array"]);
533
534                CHECK(j_const["integer"] == Json(1));
535                CHECK(j_const[typename Json::object_t::key_type("integer")] == j["integer"]);
536
537                CHECK(j_const["boolean"] == Json(true));
538                CHECK(j_const[typename Json::object_t::key_type("boolean")] == j["boolean"]);
539
540                CHECK(j_const["null"] == Json(nullptr));
541                CHECK(j_const[typename Json::object_t::key_type("null")] == j["null"]);
542
543                CHECK(j_const["string"] == Json("hello world"));
544                CHECK(j_const[typename Json::object_t::key_type("string")] == j["string"]);
545
546                CHECK(j_const["floating"] == Json(42.23));
547                CHECK(j_const[typename Json::object_t::key_type("floating")] == j["floating"]);
548
549                CHECK(j_const["object"] == Json::object());
550                CHECK(j_const[typename Json::object_t::key_type("object")] == j["object"]);
551
552                CHECK(j_const["array"] == Json({1, 2, 3}));
553                CHECK(j_const[typename Json::object_t::key_type("array")] == j["array"]);
554            }
555
556#ifdef JSON_HAS_CPP_17
557            SECTION("access within bounds (string_view)")
558            {
559                CHECK(j["integer"] == Json(1));
560                CHECK(j[std::string_view("integer")] == j["integer"]);
561
562                CHECK(j["unsigned"] == Json(1u));
563                CHECK(j[std::string_view("unsigned")] == j["unsigned"]);
564
565                CHECK(j["boolean"] == Json(true));
566                CHECK(j[std::string_view("boolean")] == j["boolean"]);
567
568                CHECK(j["null"] == Json(nullptr));
569                CHECK(j[std::string_view("null")] == j["null"]);
570
571                CHECK(j["string"] == Json("hello world"));
572                CHECK(j[std::string_view("string")] == j["string"]);
573
574                CHECK(j["floating"] == Json(42.23));
575                CHECK(j[std::string_view("floating")] == j["floating"]);
576
577                CHECK(j["object"] == Json::object());
578                CHECK(j[std::string_view("object")] == j["object"]);
579
580                CHECK(j["array"] == Json({1, 2, 3}));
581                CHECK(j[std::string_view("array")] == j["array"]);
582
583                CHECK(j_const["integer"] == Json(1));
584                CHECK(j_const[std::string_view("integer")] == j["integer"]);
585
586                CHECK(j_const["boolean"] == Json(true));
587                CHECK(j_const[std::string_view("boolean")] == j["boolean"]);
588
589                CHECK(j_const["null"] == Json(nullptr));
590                CHECK(j_const[std::string_view("null")] == j["null"]);
591
592                CHECK(j_const["string"] == Json("hello world"));
593                CHECK(j_const[std::string_view("string")] == j["string"]);
594
595                CHECK(j_const["floating"] == Json(42.23));
596                CHECK(j_const[std::string_view("floating")] == j["floating"]);
597
598                CHECK(j_const["object"] == Json::object());
599                CHECK(j_const[std::string_view("object")] == j["object"]);
600
601                CHECK(j_const["array"] == Json({1, 2, 3}));
602                CHECK(j_const[std::string_view("array")] == j["array"]);
603            }
604#endif
605
606            SECTION("access on non-object type")
607            {
608                SECTION("null")
609                {
610                    Json j_nonobject(Json::value_t::null);
611                    Json j_nonobject2(Json::value_t::null);
612                    const Json j_const_nonobject(j_nonobject);
613
614                    CHECK_NOTHROW(j_nonobject["foo"]);
615                    CHECK_NOTHROW(j_nonobject2[typename Json::object_t::key_type("foo")]);
616                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", typename Json::type_error&);
617                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", typename Json::type_error&);
618
619#ifdef JSON_HAS_CPP_17
620                    CHECK_NOTHROW(j_nonobject2[std::string_view("foo")]);
621                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", typename Json::type_error&);
622#endif
623                }
624
625                SECTION("boolean")
626                {
627                    Json j_nonobject(Json::value_t::boolean);
628                    const Json j_const_nonobject(j_nonobject);
629                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
630                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
631                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")],
632                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
633                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
634                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
635                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
636                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
637
638#ifdef JSON_HAS_CPP_17
639                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
640                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", typename Json::type_error&);
641#endif
642                }
643
644                SECTION("string")
645                {
646                    Json j_nonobject(Json::value_t::string);
647                    const Json j_const_nonobject(j_nonobject);
648                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
649                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
650                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")],
651                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
652                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
653                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
654                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
655                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
656
657#ifdef JSON_HAS_CPP_17
658                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
659                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with string", typename Json::type_error&);
660#endif
661                }
662
663                SECTION("array")
664                {
665                    Json j_nonobject(Json::value_t::array);
666                    const Json j_const_nonobject(j_nonobject);
667                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
668                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
669                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
670                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
671                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
672                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
673                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
674
675#ifdef JSON_HAS_CPP_17
676                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
677                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with array", typename Json::type_error&);
678#endif
679                }
680
681                SECTION("number (integer)")
682                {
683                    Json j_nonobject(Json::value_t::number_integer);
684                    const Json j_const_nonobject(j_nonobject);
685                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
686                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
687                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")],
688                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
689                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
690                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
691                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
692                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
693
694#ifdef JSON_HAS_CPP_17
695                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
696                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
697#endif
698                }
699
700                SECTION("number (unsigned)")
701                {
702                    Json j_nonobject(Json::value_t::number_unsigned);
703                    const Json j_const_nonobject(j_nonobject);
704                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
705                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
706                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")],
707                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
708                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
709                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
710                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
711                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
712
713#ifdef JSON_HAS_CPP_17
714                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
715                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
716#endif
717                }
718
719                SECTION("number (floating-point)")
720                {
721                    Json j_nonobject(Json::value_t::number_float);
722                    const Json j_const_nonobject(j_nonobject);
723                    CHECK_THROWS_WITH_AS(j_nonobject["foo"],
724                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
725                    CHECK_THROWS_WITH_AS(j_nonobject[typename Json::object_t::key_type("foo")],
726                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
727                    CHECK_THROWS_WITH_AS(j_const_nonobject["foo"],
728                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
729                    CHECK_THROWS_WITH_AS(j_const_nonobject[typename Json::object_t::key_type("foo")],
730                                         "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
731
732#ifdef JSON_HAS_CPP_17
733                    CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
734                    CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", typename Json::type_error&);
735#endif
736                }
737            }
738        }
739
740        SECTION("remove specified element")
741        {
742            SECTION("remove element by key")
743            {
744                CHECK(j.find("integer") != j.end());
745                CHECK(j.erase("integer") == 1);
746                CHECK(j.find("integer") == j.end());
747                CHECK(j.erase("integer") == 0);
748
749                CHECK(j.find("unsigned") != j.end());
750                CHECK(j.erase("unsigned") == 1);
751                CHECK(j.find("unsigned") == j.end());
752                CHECK(j.erase("unsigned") == 0);
753
754                CHECK(j.find("boolean") != j.end());
755                CHECK(j.erase("boolean") == 1);
756                CHECK(j.find("boolean") == j.end());
757                CHECK(j.erase("boolean") == 0);
758
759                CHECK(j.find("null") != j.end());
760                CHECK(j.erase("null") == 1);
761                CHECK(j.find("null") == j.end());
762                CHECK(j.erase("null") == 0);
763
764                CHECK(j.find("string") != j.end());
765                CHECK(j.erase("string") == 1);
766                CHECK(j.find("string") == j.end());
767                CHECK(j.erase("string") == 0);
768
769                CHECK(j.find("floating") != j.end());
770                CHECK(j.erase("floating") == 1);
771                CHECK(j.find("floating") == j.end());
772                CHECK(j.erase("floating") == 0);
773
774                CHECK(j.find("object") != j.end());
775                CHECK(j.erase("object") == 1);
776                CHECK(j.find("object") == j.end());
777                CHECK(j.erase("object") == 0);
778
779                CHECK(j.find("array") != j.end());
780                CHECK(j.erase("array") == 1);
781                CHECK(j.find("array") == j.end());
782                CHECK(j.erase("array") == 0);
783            }
784
785#ifdef JSON_HAS_CPP_17
786            SECTION("remove element by key (string_view)")
787            {
788                CHECK(j.find(std::string_view("integer")) != j.end());
789                CHECK(j.erase(std::string_view("integer")) == 1);
790                CHECK(j.find(std::string_view("integer")) == j.end());
791                CHECK(j.erase(std::string_view("integer")) == 0);
792
793                CHECK(j.find(std::string_view("unsigned")) != j.end());
794                CHECK(j.erase(std::string_view("unsigned")) == 1);
795                CHECK(j.find(std::string_view("unsigned")) == j.end());
796                CHECK(j.erase(std::string_view("unsigned")) == 0);
797
798                CHECK(j.find(std::string_view("boolean")) != j.end());
799                CHECK(j.erase(std::string_view("boolean")) == 1);
800                CHECK(j.find(std::string_view("boolean")) == j.end());
801                CHECK(j.erase(std::string_view("boolean")) == 0);
802
803                CHECK(j.find(std::string_view("null")) != j.end());
804                CHECK(j.erase(std::string_view("null")) == 1);
805                CHECK(j.find(std::string_view("null")) == j.end());
806                CHECK(j.erase(std::string_view("null")) == 0);
807
808                CHECK(j.find(std::string_view("string")) != j.end());
809                CHECK(j.erase(std::string_view("string")) == 1);
810                CHECK(j.find(std::string_view("string")) == j.end());
811                CHECK(j.erase(std::string_view("string")) == 0);
812
813                CHECK(j.find(std::string_view("floating")) != j.end());
814                CHECK(j.erase(std::string_view("floating")) == 1);
815                CHECK(j.find(std::string_view("floating")) == j.end());
816                CHECK(j.erase(std::string_view("floating")) == 0);
817
818                CHECK(j.find(std::string_view("object")) != j.end());
819                CHECK(j.erase(std::string_view("object")) == 1);
820                CHECK(j.find(std::string_view("object")) == j.end());
821                CHECK(j.erase(std::string_view("object")) == 0);
822
823                CHECK(j.find(std::string_view("array")) != j.end());
824                CHECK(j.erase(std::string_view("array")) == 1);
825                CHECK(j.find(std::string_view("array")) == j.end());
826                CHECK(j.erase(std::string_view("array")) == 0);
827            }
828#endif
829
830            SECTION("remove element by iterator")
831            {
832                SECTION("erase(begin())")
833                {
834                    {
835                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
836                        typename Json::iterator it2 = jobject.erase(jobject.begin());
837                        CHECK(jobject == Json({{"b", 1}, {"c", 17u}}));
838                        CHECK(*it2 == Json(1));
839                    }
840                    {
841                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
842                        typename Json::const_iterator it2 = jobject.erase(jobject.cbegin());
843                        CHECK(jobject == Json({{"b", 1}, {"c", 17u}}));
844                        CHECK(*it2 == Json(1));
845                    }
846                }
847
848                SECTION("erase(begin(), end())")
849                {
850                    {
851                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
852                        typename Json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
853                        CHECK(jobject == Json::object());
854                        CHECK(it2 == jobject.end());
855                    }
856                    {
857                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
858                        typename Json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
859                        CHECK(jobject == Json::object());
860                        CHECK(it2 == jobject.cend());
861                    }
862                }
863
864                SECTION("erase(begin(), begin())")
865                {
866                    {
867                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
868                        typename Json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
869                        CHECK(jobject == Json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
870                        CHECK(*it2 == Json("a"));
871                    }
872                    {
873                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
874                        typename Json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
875                        CHECK(jobject == Json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
876                        CHECK(*it2 == Json("a"));
877                    }
878                }
879
880                SECTION("erase at offset")
881                {
882                    {
883                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
884                        typename Json::iterator it = jobject.find("b");
885                        typename Json::iterator it2 = jobject.erase(it);
886                        CHECK(jobject == Json({{"a", "a"}, {"c", 17u}}));
887                        CHECK(*it2 == Json(17));
888                    }
889                    {
890                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
891                        typename Json::const_iterator it = jobject.find("b");
892                        typename Json::const_iterator it2 = jobject.erase(it);
893                        CHECK(jobject == Json({{"a", "a"}, {"c", 17u}}));
894                        CHECK(*it2 == Json(17));
895                    }
896                }
897
898                SECTION("erase subrange")
899                {
900                    {
901                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
902                        typename Json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
903                        CHECK(jobject == Json({{"a", "a"}, {"e", true}}));
904                        CHECK(*it2 == Json(true));
905                    }
906                    {
907                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
908                        typename Json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
909                        CHECK(jobject == Json({{"a", "a"}, {"e", true}}));
910                        CHECK(*it2 == Json(true));
911                    }
912                }
913
914                SECTION("different objects")
915                {
916                    {
917                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
918                        Json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
919                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.begin()),
920                                             "[json.exception.invalid_iterator.202] iterator does not fit current value", typename Json::invalid_iterator&);
921                        CHECK_THROWS_WITH_AS(jobject.erase(jobject.begin(), jobject2.end()),
922                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
923                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.begin(), jobject.end()),
924                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
925                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.begin(), jobject2.end()),
926                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
927                    }
928                    {
929                        Json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
930                        Json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
931                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.cbegin()),
932                                             "[json.exception.invalid_iterator.202] iterator does not fit current value", typename Json::invalid_iterator&);
933                        CHECK_THROWS_WITH_AS(jobject.erase(jobject.cbegin(), jobject2.cend()),
934                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
935                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.cbegin(), jobject.cend()),
936                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
937                        CHECK_THROWS_WITH_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()),
938                                             "[json.exception.invalid_iterator.203] iterators do not fit current value", typename Json::invalid_iterator&);
939                    }
940                }
941            }
942
943            SECTION("remove element by key in non-object type")
944            {
945                SECTION("null")
946                {
947                    Json j_nonobject(Json::value_t::null);
948                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with null", typename Json::type_error&);
949
950#ifdef JSON_HAS_CPP_17
951                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with null", typename Json::type_error&);
952#endif
953                }
954
955                SECTION("boolean")
956                {
957                    Json j_nonobject(Json::value_t::boolean);
958                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with boolean", typename Json::type_error&);
959
960#ifdef JSON_HAS_CPP_17
961                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with boolean", typename Json::type_error&);
962#endif
963                }
964
965                SECTION("string")
966                {
967                    Json j_nonobject(Json::value_t::string);
968                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with string", typename Json::type_error&);
969
970#ifdef JSON_HAS_CPP_17
971                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with string", typename Json::type_error&);
972#endif
973                }
974
975                SECTION("array")
976                {
977                    Json j_nonobject(Json::value_t::array);
978                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with array", typename Json::type_error&);
979
980#ifdef JSON_HAS_CPP_17
981                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with array", typename Json::type_error&);
982#endif
983                }
984
985                SECTION("number (integer)")
986                {
987                    Json j_nonobject(Json::value_t::number_integer);
988                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number", typename Json::type_error&);
989
990#ifdef JSON_HAS_CPP_17
991                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with number", typename Json::type_error&);
992#endif
993                }
994
995                SECTION("number (floating-point)")
996                {
997                    Json j_nonobject(Json::value_t::number_float);
998                    CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number", typename Json::type_error&);
999
1000#ifdef JSON_HAS_CPP_17
1001                    CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with number", typename Json::type_error&);
1002#endif
1003                }
1004            }
1005        }
1006
1007        SECTION("find an element in an object")
1008        {
1009            SECTION("existing element")
1010            {
1011                for (const auto* key :
1012                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1013                        })
1014                {
1015                    CHECK(j.find(key) != j.end());
1016                    CHECK(*j.find(key) == j.at(key));
1017                    CHECK(j_const.find(key) != j_const.end());
1018                    CHECK(*j_const.find(key) == j_const.at(key));
1019                }
1020#ifdef JSON_HAS_CPP_17
1021                for (const std::string_view key :
1022                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1023                        })
1024                {
1025                    CHECK(j.find(key) != j.end());
1026                    CHECK(*j.find(key) == j.at(key));
1027                    CHECK(j_const.find(key) != j_const.end());
1028                    CHECK(*j_const.find(key) == j_const.at(key));
1029                }
1030#endif
1031            }
1032
1033            SECTION("nonexisting element")
1034            {
1035                CHECK(j.find("foo") == j.end());
1036                CHECK(j_const.find("foo") == j_const.end());
1037
1038#ifdef JSON_HAS_CPP_17
1039                CHECK(j.find(std::string_view("foo")) == j.end());
1040                CHECK(j_const.find(std::string_view("foo")) == j_const.end());
1041#endif
1042            }
1043
1044            SECTION("all types")
1045            {
1046                SECTION("null")
1047                {
1048                    Json j_nonarray(Json::value_t::null);
1049                    const Json j_nonarray_const(j_nonarray);
1050
1051                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1052                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1053
1054#ifdef JSON_HAS_CPP_17
1055                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1056                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1057#endif
1058                }
1059
1060                SECTION("string")
1061                {
1062                    Json j_nonarray(Json::value_t::string);
1063                    const Json j_nonarray_const(j_nonarray);
1064
1065                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1066                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1067
1068#ifdef JSON_HAS_CPP_17
1069                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1070                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1071#endif
1072                }
1073
1074                SECTION("object")
1075                {
1076                    Json j_nonarray(Json::value_t::object);
1077                    const Json j_nonarray_const(j_nonarray);
1078
1079                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1080                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1081
1082#ifdef JSON_HAS_CPP_17
1083                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1084                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1085#endif
1086                }
1087
1088                SECTION("array")
1089                {
1090                    Json j_nonarray(Json::value_t::array);
1091                    const Json j_nonarray_const(j_nonarray);
1092
1093                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1094                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1095
1096#ifdef JSON_HAS_CPP_17
1097                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1098                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1099#endif
1100                }
1101
1102                SECTION("boolean")
1103                {
1104                    Json j_nonarray(Json::value_t::boolean);
1105                    const Json j_nonarray_const(j_nonarray);
1106
1107                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1108                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1109
1110#ifdef JSON_HAS_CPP_17
1111                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1112                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1113#endif
1114                }
1115
1116                SECTION("number (integer)")
1117                {
1118                    Json j_nonarray(Json::value_t::number_integer);
1119                    const Json j_nonarray_const(j_nonarray);
1120
1121                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1122                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1123
1124#ifdef JSON_HAS_CPP_17
1125                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1126                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1127#endif
1128                }
1129
1130                SECTION("number (unsigned)")
1131                {
1132                    Json j_nonarray(Json::value_t::number_unsigned);
1133                    const Json j_nonarray_const(j_nonarray);
1134
1135                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1136                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1137
1138#ifdef JSON_HAS_CPP_17
1139                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1140                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1141#endif
1142                }
1143
1144                SECTION("number (floating-point)")
1145                {
1146                    Json j_nonarray(Json::value_t::number_float);
1147                    const Json j_nonarray_const(j_nonarray);
1148
1149                    CHECK(j_nonarray.find("foo") == j_nonarray.end());
1150                    CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
1151
1152#ifdef JSON_HAS_CPP_17
1153                    CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
1154                    CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
1155#endif
1156                }
1157            }
1158        }
1159
1160        SECTION("count keys in an object")
1161        {
1162            SECTION("existing element")
1163            {
1164                for (const auto* key :
1165                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1166                        })
1167                {
1168                    CHECK(j.count(key) == 1);
1169                    CHECK(j_const.count(key) == 1);
1170                }
1171#ifdef JSON_HAS_CPP_17
1172                for (const std::string_view key :
1173                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1174                        })
1175                {
1176                    CHECK(j.count(key) == 1);
1177                    CHECK(j_const.count(key) == 1);
1178                }
1179#endif
1180            }
1181
1182            SECTION("nonexisting element")
1183            {
1184                CHECK(j.count("foo") == 0);
1185                CHECK(j_const.count("foo") == 0);
1186
1187#ifdef JSON_HAS_CPP_17
1188                CHECK(j.count(std::string_view("foo")) == 0);
1189                CHECK(j_const.count(std::string_view("foo")) == 0);
1190#endif
1191            }
1192
1193            SECTION("all types")
1194            {
1195                SECTION("null")
1196                {
1197                    Json j_nonobject(Json::value_t::null);
1198                    const Json j_nonobject_const(Json::value_t::null);
1199
1200                    CHECK(j_nonobject.count("foo") == 0);
1201                    CHECK(j_nonobject_const.count("foo") == 0);
1202
1203#ifdef JSON_HAS_CPP_17
1204                    CHECK(j.count(std::string_view("foo")) == 0);
1205                    CHECK(j_const.count(std::string_view("foo")) == 0);
1206#endif
1207                }
1208
1209                SECTION("string")
1210                {
1211                    Json j_nonobject(Json::value_t::string);
1212                    const Json j_nonobject_const(Json::value_t::string);
1213
1214                    CHECK(j_nonobject.count("foo") == 0);
1215                    CHECK(j_nonobject_const.count("foo") == 0);
1216
1217#ifdef JSON_HAS_CPP_17
1218                    CHECK(j.count(std::string_view("foo")) == 0);
1219                    CHECK(j_const.count(std::string_view("foo")) == 0);
1220#endif
1221                }
1222
1223                SECTION("object")
1224                {
1225                    Json j_nonobject(Json::value_t::object);
1226                    const Json j_nonobject_const(Json::value_t::object);
1227
1228                    CHECK(j_nonobject.count("foo") == 0);
1229                    CHECK(j_nonobject_const.count("foo") == 0);
1230
1231#ifdef JSON_HAS_CPP_17
1232                    CHECK(j.count(std::string_view("foo")) == 0);
1233                    CHECK(j_const.count(std::string_view("foo")) == 0);
1234#endif
1235                }
1236
1237                SECTION("array")
1238                {
1239                    Json j_nonobject(Json::value_t::array);
1240                    const Json j_nonobject_const(Json::value_t::array);
1241
1242                    CHECK(j_nonobject.count("foo") == 0);
1243                    CHECK(j_nonobject_const.count("foo") == 0);
1244
1245#ifdef JSON_HAS_CPP_17
1246                    CHECK(j.count(std::string_view("foo")) == 0);
1247                    CHECK(j_const.count(std::string_view("foo")) == 0);
1248#endif
1249                }
1250
1251                SECTION("boolean")
1252                {
1253                    Json j_nonobject(Json::value_t::boolean);
1254                    const Json j_nonobject_const(Json::value_t::boolean);
1255
1256                    CHECK(j_nonobject.count("foo") == 0);
1257                    CHECK(j_nonobject_const.count("foo") == 0);
1258
1259#ifdef JSON_HAS_CPP_17
1260                    CHECK(j.count(std::string_view("foo")) == 0);
1261                    CHECK(j_const.count(std::string_view("foo")) == 0);
1262#endif
1263                }
1264
1265                SECTION("number (integer)")
1266                {
1267                    Json j_nonobject(Json::value_t::number_integer);
1268                    const Json j_nonobject_const(Json::value_t::number_integer);
1269
1270                    CHECK(j_nonobject.count("foo") == 0);
1271                    CHECK(j_nonobject_const.count("foo") == 0);
1272
1273#ifdef JSON_HAS_CPP_17
1274                    CHECK(j.count(std::string_view("foo")) == 0);
1275                    CHECK(j_const.count(std::string_view("foo")) == 0);
1276#endif
1277                }
1278
1279                SECTION("number (unsigned)")
1280                {
1281                    Json j_nonobject(Json::value_t::number_unsigned);
1282                    const Json j_nonobject_const(Json::value_t::number_unsigned);
1283
1284                    CHECK(j_nonobject.count("foo") == 0);
1285                    CHECK(j_nonobject_const.count("foo") == 0);
1286
1287#ifdef JSON_HAS_CPP_17
1288                    CHECK(j.count(std::string_view("foo")) == 0);
1289                    CHECK(j_const.count(std::string_view("foo")) == 0);
1290#endif
1291                }
1292
1293                SECTION("number (floating-point)")
1294                {
1295                    Json j_nonobject(Json::value_t::number_float);
1296                    const Json j_nonobject_const(Json::value_t::number_float);
1297
1298                    CHECK(j_nonobject.count("foo") == 0);
1299                    CHECK(j_nonobject_const.count("foo") == 0);
1300
1301#ifdef JSON_HAS_CPP_17
1302                    CHECK(j.count(std::string_view("foo")) == 0);
1303                    CHECK(j_const.count(std::string_view("foo")) == 0);
1304#endif
1305                }
1306            }
1307        }
1308
1309        SECTION("check existence of key in an object")
1310        {
1311            SECTION("existing element")
1312            {
1313                for (const auto* key :
1314                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1315                        })
1316                {
1317                    CHECK(j.contains(key) == true);
1318                    CHECK(j_const.contains(key) == true);
1319                }
1320
1321#ifdef JSON_HAS_CPP_17
1322                for (const std::string_view key :
1323                        {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
1324                        })
1325                {
1326                    CHECK(j.contains(key) == true);
1327                    CHECK(j_const.contains(key) == true);
1328                }
1329#endif
1330            }
1331
1332            SECTION("nonexisting element")
1333            {
1334                CHECK(j.contains("foo") == false);
1335                CHECK(j_const.contains("foo") == false);
1336
1337#ifdef JSON_HAS_CPP_17
1338                CHECK(j.contains(std::string_view("foo")) == false);
1339                CHECK(j_const.contains(std::string_view("foo")) == false);
1340#endif
1341            }
1342
1343            SECTION("all types")
1344            {
1345                SECTION("null")
1346                {
1347                    Json j_nonobject(Json::value_t::null);
1348                    const Json j_nonobject_const(Json::value_t::null);
1349
1350                    CHECK(j_nonobject.contains("foo") == false);
1351                    CHECK(j_nonobject_const.contains("foo") == false);
1352
1353#ifdef JSON_HAS_CPP_17
1354                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1355                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1356#endif
1357                }
1358
1359                SECTION("string")
1360                {
1361                    Json j_nonobject(Json::value_t::string);
1362                    const Json j_nonobject_const(Json::value_t::string);
1363
1364                    CHECK(j_nonobject.contains("foo") == false);
1365                    CHECK(j_nonobject_const.contains("foo") == false);
1366
1367#ifdef JSON_HAS_CPP_17
1368                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1369                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1370#endif
1371                }
1372
1373                SECTION("object")
1374                {
1375                    Json j_nonobject(Json::value_t::object);
1376                    const Json j_nonobject_const(Json::value_t::object);
1377
1378                    CHECK(j_nonobject.contains("foo") == false);
1379                    CHECK(j_nonobject_const.contains("foo") == false);
1380
1381#ifdef JSON_HAS_CPP_17
1382                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1383                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1384#endif
1385                }
1386
1387                SECTION("array")
1388                {
1389                    Json j_nonobject(Json::value_t::array);
1390                    const Json j_nonobject_const(Json::value_t::array);
1391
1392                    CHECK(j_nonobject.contains("foo") == false);
1393                    CHECK(j_nonobject_const.contains("foo") == false);
1394
1395#ifdef JSON_HAS_CPP_17
1396                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1397                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1398#endif
1399                }
1400
1401                SECTION("boolean")
1402                {
1403                    Json j_nonobject(Json::value_t::boolean);
1404                    const Json j_nonobject_const(Json::value_t::boolean);
1405
1406                    CHECK(j_nonobject.contains("foo") == false);
1407                    CHECK(j_nonobject_const.contains("foo") == false);
1408
1409#ifdef JSON_HAS_CPP_17
1410                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1411                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1412#endif
1413                }
1414
1415                SECTION("number (integer)")
1416                {
1417                    Json j_nonobject(Json::value_t::number_integer);
1418                    const Json j_nonobject_const(Json::value_t::number_integer);
1419
1420                    CHECK(j_nonobject.contains("foo") == false);
1421                    CHECK(j_nonobject_const.contains("foo") == false);
1422
1423#ifdef JSON_HAS_CPP_17
1424                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1425                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1426#endif
1427                }
1428
1429                SECTION("number (unsigned)")
1430                {
1431                    Json j_nonobject(Json::value_t::number_unsigned);
1432                    const Json j_nonobject_const(Json::value_t::number_unsigned);
1433
1434                    CHECK(j_nonobject.contains("foo") == false);
1435                    CHECK(j_nonobject_const.contains("foo") == false);
1436
1437#ifdef JSON_HAS_CPP_17
1438                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1439                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1440#endif
1441                }
1442
1443                SECTION("number (floating-point)")
1444                {
1445                    Json j_nonobject(Json::value_t::number_float);
1446                    const Json j_nonobject_const(Json::value_t::number_float);
1447                    CHECK(j_nonobject.contains("foo") == false);
1448                    CHECK(j_nonobject_const.contains("foo") == false);
1449#ifdef JSON_HAS_CPP_17
1450                    CHECK(j_nonobject.contains(std::string_view("foo")) == false);
1451                    CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
1452#endif
1453                }
1454            }
1455        }
1456    }
1457}
1458
1459#if !defined(JSON_NOEXCEPTION)
1460TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nlohmann::ordered_json)
1461{
1462    SECTION("object")
1463    {
1464        Json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", Json::object()}, {"array", {1, 2, 3}}};
1465        const Json j_const = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", Json::object()}, {"array", {1, 2, 3}}};
1466
1467        SECTION("access specified element with default value")
1468        {
1469            SECTION("given a JSON pointer")
1470            {
1471                SECTION("access non-existing value")
1472                {
1473                    CHECK(j.value("/not/existing"_json_pointer, 2) == 2);
1474                    CHECK(j.value("/not/existing"_json_pointer, 2u) == 2u);
1475                    CHECK(j.value("/not/existing"_json_pointer, false) == false);
1476                    CHECK(j.value("/not/existing"_json_pointer, "bar") == "bar");
1477                    CHECK(j.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
1478                    CHECK(j.value("/not/existing"_json_pointer, Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
1479                    CHECK(j.value("/not/existing"_json_pointer, Json({10, 100})) == Json({10, 100}));
1480
1481                    CHECK(j_const.value("/not/existing"_json_pointer, 2) == 2);
1482                    CHECK(j_const.value("/not/existing"_json_pointer, 2u) == 2u);
1483                    CHECK(j_const.value("/not/existing"_json_pointer, false) == false);
1484                    CHECK(j_const.value("/not/existing"_json_pointer, "bar") == "bar");
1485                    CHECK(j_const.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
1486                    CHECK(j_const.value("/not/existing"_json_pointer, Json({{"foo", "bar"}})) == Json({{"foo", "bar"}}));
1487                    CHECK(j_const.value("/not/existing"_json_pointer, Json({10, 100})) == Json({10, 100}));
1488                }
1489            }
1490        }
1491    }
1492}
1493#endif
1494
1495// TODO(falbrechtskirchinger) merge with the other test case; clean up
1496TEST_CASE_TEMPLATE("element access 2 (additional value() tests)", Json, nlohmann::json, nlohmann::ordered_json)
1497{
1498    using string_t = typename Json::string_t;
1499    using number_integer_t = typename Json::number_integer_t;
1500
1501    // test assumes string_t and object_t::key_type are the same
1502    REQUIRE(std::is_same<string_t, typename Json::object_t::key_type>::value);
1503
1504    Json j
1505    {
1506        {"foo", "bar"},
1507        {"baz", 42}
1508    };
1509
1510    const char* cpstr = "default";
1511    const char castr[] = "default"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1512    string_t str = "default";
1513
1514    number_integer_t integer = 69;
1515    std::size_t size = 69;
1516
1517    SECTION("deduced ValueType")
1518    {
1519        SECTION("literal key")
1520        {
1521            CHECK(j.value("foo", "default") == "bar");
1522            CHECK(j.value("foo", cpstr) == "bar");
1523            CHECK(j.value("foo", castr) == "bar");
1524            CHECK(j.value("foo", str) == "bar");
1525            // this test is in fact different than the one below,
1526            // because of 0 considering const char * overloads
1527            // where as any other number does not
1528            CHECK(j.value("baz", 0) == 42);
1529            CHECK(j.value("baz", 47) == 42);
1530            CHECK(j.value("baz", integer) == 42);
1531            CHECK(j.value("baz", size) == 42);
1532
1533            CHECK(j.value("bar", "default") == "default");
1534            CHECK(j.value("bar", 0) == 0);
1535            CHECK(j.value("bar", 47) == 47);
1536            CHECK(j.value("bar", integer) == integer);
1537            CHECK(j.value("bar", size) == size);
1538
1539            CHECK_THROWS_WITH_AS(Json().value("foo", "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1540            CHECK_THROWS_WITH_AS(Json().value("foo", str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1541        }
1542
1543        SECTION("const char * key")
1544        {
1545            const char* key = "foo";
1546            const char* key2 = "baz";
1547            const char* key_notfound = "bar";
1548
1549            CHECK(j.value(key, "default") == "bar");
1550            CHECK(j.value(key, cpstr) == "bar");
1551            CHECK(j.value(key, castr) == "bar");
1552            CHECK(j.value(key, str) == "bar");
1553            CHECK(j.value(key2, 0) == 42);
1554            CHECK(j.value(key2, 47) == 42);
1555            CHECK(j.value(key2, integer) == 42);
1556            CHECK(j.value(key2, size) == 42);
1557
1558            CHECK(j.value(key_notfound, "default") == "default");
1559            CHECK(j.value(key_notfound, 0) == 0);
1560            CHECK(j.value(key_notfound, 47) == 47);
1561            CHECK(j.value(key_notfound, integer) == integer);
1562            CHECK(j.value(key_notfound, size) == size);
1563
1564            CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1565            CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1566        }
1567
1568        SECTION("const char(&)[] key")
1569        {
1570            const char key[] = "foo"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1571            const char key2[] = "baz"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1572            const char key_notfound[] = "bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1573
1574            CHECK(j.value(key, "default") == "bar");
1575            CHECK(j.value(key, cpstr) == "bar");
1576            CHECK(j.value(key, castr) == "bar");
1577            CHECK(j.value(key, str) == "bar");
1578            CHECK(j.value(key2, 0) == 42);
1579            CHECK(j.value(key2, 47) == 42);
1580            CHECK(j.value(key2, integer) == 42);
1581            CHECK(j.value(key2, size) == 42);
1582
1583            CHECK(j.value(key_notfound, "default") == "default");
1584            CHECK(j.value(key_notfound, 0) == 0);
1585            CHECK(j.value(key_notfound, 47) == 47);
1586            CHECK(j.value(key_notfound, integer) == integer);
1587            CHECK(j.value(key_notfound, size) == size);
1588
1589            CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1590            CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1591        }
1592
1593        SECTION("string_t/object_t::key_type key")
1594        {
1595            string_t key = "foo";
1596            string_t key2 = "baz";
1597            string_t key_notfound = "bar";
1598
1599            CHECK(j.value(key, "default") == "bar");
1600            CHECK(j.value(key, cpstr) == "bar");
1601            CHECK(j.value(key, castr) == "bar");
1602            CHECK(j.value(key, str) == "bar");
1603            CHECK(j.value(key2, 0) == 42);
1604            CHECK(j.value(key2, 47) == 42);
1605            CHECK(j.value(key2, integer) == 42);
1606            CHECK(j.value(key2, size) == 42);
1607
1608            CHECK(j.value(key_notfound, "default") == "default");
1609            CHECK(j.value(key_notfound, 0) == 0);
1610            CHECK(j.value(key_notfound, 47) == 47);
1611            CHECK(j.value(key_notfound, integer) == integer);
1612            CHECK(j.value(key_notfound, size) == size);
1613
1614            CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1615            CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1616        }
1617
1618#ifdef JSON_HAS_CPP_17
1619        SECTION("std::string_view key")
1620        {
1621            std::string_view key = "foo";
1622            std::string_view key2 = "baz";
1623            std::string_view key_notfound = "bar";
1624
1625            CHECK(j.value(key, "default") == "bar");
1626            CHECK(j.value(key, cpstr) == "bar");
1627            CHECK(j.value(key, castr) == "bar");
1628            CHECK(j.value(key, str) == "bar");
1629            CHECK(j.value(key2, 0) == 42);
1630            CHECK(j.value(key2, 47) == 42);
1631            CHECK(j.value(key2, integer) == 42);
1632            CHECK(j.value(key2, size) == 42);
1633
1634            CHECK(j.value(key_notfound, "default") == "default");
1635            CHECK(j.value(key_notfound, 0) == 0);
1636            CHECK(j.value(key_notfound, 47) == 47);
1637            CHECK(j.value(key_notfound, integer) == integer);
1638            CHECK(j.value(key_notfound, size) == size);
1639
1640            CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1641            CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1642        }
1643#endif
1644    }
1645
1646    SECTION("explicit ValueType")
1647    {
1648        SECTION("literal key")
1649        {
1650            CHECK(j.template value<string_t>("foo", "default") == "bar");
1651            CHECK(j.template value<string_t>("foo", cpstr) == "bar");
1652            CHECK(j.template value<string_t>("foo", castr) == "bar");
1653            CHECK(j.template value<string_t>("foo", str) == "bar");
1654            CHECK(j.template value<number_integer_t>("baz", 0) == 42);
1655            CHECK(j.template value<number_integer_t>("baz", 47) == 42);
1656            CHECK(j.template value<number_integer_t>("baz", integer) == 42);
1657            CHECK(j.template value<std::size_t>("baz", 0) == 42);
1658            CHECK(j.template value<std::size_t>("baz", 47) == 42);
1659            CHECK(j.template value<std::size_t>("baz", size) == 42);
1660
1661            CHECK(j.template value<string_t>("bar", "default") == "default");
1662            CHECK(j.template value<number_integer_t>("bar", 0) == 0);
1663            CHECK(j.template value<number_integer_t>("bar", 47) == 47);
1664            CHECK(j.template value<number_integer_t>("bar", integer) == integer);
1665            CHECK(j.template value<std::size_t>("bar", 0) == 0);
1666            CHECK(j.template value<std::size_t>("bar", 47) == 47);
1667            CHECK(j.template value<std::size_t>("bar", size) == size);
1668
1669            CHECK_THROWS_WITH_AS(Json().template value<string_t>("foo", "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1670            CHECK_THROWS_WITH_AS(Json().template value<string_t>("foo", str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1671        }
1672
1673        SECTION("const char * key")
1674        {
1675            const char* key = "foo";
1676            const char* key2 = "baz";
1677            const char* key_notfound = "bar";
1678
1679            CHECK(j.template value<string_t>(key, "default") == "bar");
1680            CHECK(j.template value<string_t>(key, cpstr) == "bar");
1681            CHECK(j.template value<string_t>(key, castr) == "bar");
1682            CHECK(j.template value<string_t>(key, str) == "bar");
1683            CHECK(j.template value<number_integer_t>(key2, 0) == 42);
1684            CHECK(j.template value<number_integer_t>(key2, 47) == 42);
1685            CHECK(j.template value<number_integer_t>(key2, integer) == 42);
1686            CHECK(j.template value<std::size_t>(key2, 0) == 42);
1687            CHECK(j.template value<std::size_t>(key2, 47) == 42);
1688            CHECK(j.template value<std::size_t>(key2, size) == 42);
1689
1690            CHECK(j.template value<string_t>(key_notfound, "default") == "default");
1691            CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
1692            CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
1693            CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
1694            CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
1695            CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
1696            CHECK(j.template value<std::size_t>(key_notfound, size) == size);
1697
1698            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1699            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1700        }
1701
1702        SECTION("const char(&)[] key")
1703        {
1704            const char key[] = "foo"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1705            const char key2[] = "baz"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1706            const char key_notfound[] = "bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
1707
1708            CHECK(j.template value<string_t>(key, "default") == "bar");
1709            CHECK(j.template value<string_t>(key, cpstr) == "bar");
1710            CHECK(j.template value<string_t>(key, castr) == "bar");
1711            CHECK(j.template value<string_t>(key, str) == "bar");
1712            CHECK(j.template value<number_integer_t>(key2, 0) == 42);
1713            CHECK(j.template value<number_integer_t>(key2, 47) == 42);
1714            CHECK(j.template value<number_integer_t>(key2, integer) == 42);
1715            CHECK(j.template value<std::size_t>(key2, 0) == 42);
1716            CHECK(j.template value<std::size_t>(key2, 47) == 42);
1717            CHECK(j.template value<std::size_t>(key2, size) == 42);
1718
1719            CHECK(j.template value<string_t>(key_notfound, "default") == "default");
1720            CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
1721            CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
1722            CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
1723            CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
1724            CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
1725            CHECK(j.template value<std::size_t>(key_notfound, size) == size);
1726
1727            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1728            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1729        }
1730
1731        SECTION("string_t/object_t::key_type key")
1732        {
1733            string_t key = "foo";
1734            string_t key2 = "baz";
1735            string_t key_notfound = "bar";
1736
1737            CHECK(j.template value<string_t>(key, "default") == "bar");
1738            CHECK(j.template value<string_t>(key, cpstr) == "bar");
1739            CHECK(j.template value<string_t>(key, castr) == "bar");
1740            CHECK(j.template value<string_t>(key, str) == "bar");
1741            CHECK(j.template value<number_integer_t>(key2, 0) == 42);
1742            CHECK(j.template value<number_integer_t>(key2, 47) == 42);
1743            CHECK(j.template value<std::size_t>(key2, 0) == 42);
1744            CHECK(j.template value<std::size_t>(key2, 47) == 42);
1745
1746            CHECK(j.template value<string_t>(key_notfound, "default") == "default");
1747            CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
1748            CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
1749            CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
1750            CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
1751
1752            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1753            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1754        }
1755
1756#ifdef JSON_HAS_CPP_17
1757        SECTION("std::string_view key")
1758        {
1759            std::string_view key = "foo";
1760            std::string_view key2 = "baz";
1761            std::string_view key_notfound = "bar";
1762
1763            CHECK(j.template value<string_t>(key, "default") == "bar");
1764            CHECK(j.template value<string_t>(key, cpstr) == "bar");
1765            CHECK(j.template value<string_t>(key, castr) == "bar");
1766            CHECK(j.template value<string_t>(key, str) == "bar");
1767            CHECK(j.template value<number_integer_t>(key2, 0) == 42);
1768            CHECK(j.template value<number_integer_t>(key2, 47) == 42);
1769            CHECK(j.template value<number_integer_t>(key2, integer) == 42);
1770            CHECK(j.template value<std::size_t>(key2, 0) == 42);
1771            CHECK(j.template value<std::size_t>(key2, 47) == 42);
1772            CHECK(j.template value<std::size_t>(key2, size) == 42);
1773
1774            CHECK(j.template value<string_t>(key_notfound, "default") == "default");
1775            CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
1776            CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
1777            CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
1778            CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
1779            CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
1780            CHECK(j.template value<std::size_t>(key_notfound, size) == size);
1781
1782            CHECK(j.template value<std::string_view>(key, "default") == "bar");
1783            CHECK(j.template value<std::string_view>(key, cpstr) == "bar");
1784            CHECK(j.template value<std::string_view>(key, castr) == "bar");
1785            CHECK(j.template value<std::string_view>(key, str) == "bar");
1786
1787            CHECK(j.template value<std::string_view>(key_notfound, "default") == "default");
1788
1789            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1790            CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
1791        }
1792#endif
1793    }
1794}
1795