• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 TEST_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)
1460 TEST_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
1496 TEST_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