• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.9.1
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
32 
33 #include <nlohmann/json.hpp>
34 using nlohmann::json;
35 
36 #include <deque>
37 #include <forward_list>
38 #include <list>
39 #include <set>
40 #include <unordered_map>
41 #include <unordered_set>
42 #include <iostream>
43 #include <sstream>
44 #include <iomanip>
45 
46 #if defined(_MSC_VER)
47     #pragma warning (push)
48     #pragma warning (disable : 4189) // local variable is initialized but not referenced
49 #endif
50 
skip()51 TEST_CASE("README" * doctest::skip())
52 {
53     {
54         // redirect std::cout for the README file
55         auto old_cout_buffer = std::cout.rdbuf();
56         std::ostringstream new_stream;
57         std::cout.rdbuf(new_stream.rdbuf());
58         {
59             // create an empty structure (null)
60             json j;
61 
62             // add a number that is stored as double (note the implicit conversion of j to an object)
63             j["pi"] = 3.141;
64 
65             // add a Boolean that is stored as bool
66             j["happy"] = true;
67 
68             // add a string that is stored as std::string
69             j["name"] = "Niels";
70 
71             // add another null object by passing nullptr
72             j["nothing"] = nullptr;
73 
74             // add an object inside the object
75             j["answer"]["everything"] = 42;
76 
77             // add an array that is stored as std::vector (using an initializer list)
78             j["list"] = { 1, 0, 2 };
79 
80             // add another object (using an initializer list of pairs)
81             j["object"] = { {"currency", "USD"}, {"value", 42.99} };
82 
83             // instead, you could also write (which looks very similar to the JSON above)
84             json j2 =
85             {
86                 {"pi", 3.141},
87                 {"happy", true},
88                 {"name", "Niels"},
89                 {"nothing", nullptr},
90                 {
91                     "answer", {
92                         {"everything", 42}
93                     }
94                 },
95                 {"list", {1, 0, 2}},
96                 {
97                     "object", {
98                         {"currency", "USD"},
99                         {"value", 42.99}
100                     }
101                 }
102             };
103         }
104 
105         {
106             // ways to express the empty array []
107             json empty_array_implicit = {{}};
108             CHECK(empty_array_implicit.is_array());
109             json empty_array_explicit = json::array();
110             CHECK(empty_array_explicit.is_array());
111 
112             // a way to express the empty object {}
113             json empty_object_explicit = json::object();
114             CHECK(empty_object_explicit.is_object());
115 
116             // a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
117             json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
118             CHECK(array_not_object.is_array());
119             CHECK(array_not_object.size() == 2);
120             CHECK(array_not_object[0].is_array());
121             CHECK(array_not_object[1].is_array());
122         }
123 
124         {
125             // create object from string literal
126             json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
127 
128             // or even nicer with a raw string literal
129             auto j2 = R"(
130           {
131             "happy": true,
132             "pi": 3.141
133           }
134         )"_json;
135 
136             // or explicitly
137             auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
138 
139             // explicit conversion to string
140             std::string s = j.dump();    // {\"happy\":true,\"pi\":3.141}
141 
142             // serialization with pretty printing
143             // pass in the amount of spaces to indent
144             std::cout << j.dump(4) << std::endl;
145             // {
146             //     "happy": true,
147             //     "pi": 3.141
148             // }
149 
150             std::cout << std::setw(2) << j << std::endl;
151         }
152 
153         {
154             // create an array using push_back
155             json j;
156             j.push_back("foo");
157             j.push_back(1);
158             j.push_back(true);
159 
160             // comparison
161             bool x = (j == "[\"foo\", 1, true]"_json);  // true
162             CHECK(x == true);
163 
164             // iterate the array
165             for (json::iterator it = j.begin(); it != j.end(); ++it)
166             {
167                 std::cout << *it << '\n';
168             }
169 
170             // range-based for
171             for (auto element : j)
172             {
173                 std::cout << element << '\n';
174             }
175 
176             // getter/setter
177             const auto tmp = j[0].get<std::string>();
178             j[1] = 42;
179             bool foo{j.at(2)};
180             CHECK(foo == true);
181 
182             // other stuff
183             j.size();     // 3 entries
184             j.empty();    // false
185             j.type();     // json::value_t::array
186             j.clear();    // the array is empty again
187 
188             // create an object
189             json o;
190             o["foo"] = 23;
191             o["bar"] = false;
192             o["baz"] = 3.141;
193 
194             // find an entry
195             if (o.find("foo") != o.end())
196             {
197                 // there is an entry with key "foo"
198             }
199         }
200 
201         {
202             std::vector<int> c_vector {1, 2, 3, 4};
203             json j_vec(c_vector);
204             // [1, 2, 3, 4]
205 
206             std::deque<float> c_deque {1.2f, 2.3f, 3.4f, 5.6f};
207             json j_deque(c_deque);
208             // [1.2, 2.3, 3.4, 5.6]
209 
210             std::list<bool> c_list {true, true, false, true};
211             json j_list(c_list);
212             // [true, true, false, true]
213 
214             std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
215             json j_flist(c_flist);
216             // [12345678909876, 23456789098765, 34567890987654, 45678909876543]
217 
218             std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
219             json j_array(c_array);
220             // [1, 2, 3, 4]
221 
222             std::set<std::string> c_set {"one", "two", "three", "four", "one"};
223             json j_set(c_set); // only one entry for "one" is used
224             // ["four", "one", "three", "two"]
225 
226             std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
227             json j_uset(c_uset); // only one entry for "one" is used
228             // maybe ["two", "three", "four", "one"]
229 
230             std::multiset<std::string> c_mset {"one", "two", "one", "four"};
231             json j_mset(c_mset); // both entries for "one" are used
232             // maybe ["one", "two", "one", "four"]
233 
234             std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
235             json j_umset(c_umset); // both entries for "one" are used
236             // maybe ["one", "two", "one", "four"]
237         }
238 
239         {
240             std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
241             json j_map(c_map);
242             // {"one": 1, "two": 2, "three": 3}
243 
244             std::unordered_map<const char*, float> c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} };
245             json j_umap(c_umap);
246             // {"one": 1.2, "two": 2.3, "three": 3.4}
247 
248             std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
249             json j_mmap(c_mmap); // only one entry for key "three" is used
250             // maybe {"one": true, "two": true, "three": true}
251 
252             std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
253             json j_ummap(c_ummap); // only one entry for key "three" is used
254             // maybe {"one": true, "two": true, "three": true}
255         }
256 
257         {
258             // strings
259             std::string s1 = "Hello, world!";
260             json js = s1;
261             auto s2 = js.get<std::string>();
262 
263             // Booleans
264             bool b1 = true;
265             json jb = b1;
266             bool b2{jb};
267             CHECK(b2 == true);
268 
269             // numbers
270             int i = 42;
271             json jn = i;
272             double f{jn};
273             CHECK(f == 42);
274 
275             // etc.
276 
277             std::string vs = js.get<std::string>();
278             bool vb = jb.get<bool>();
279             CHECK(vb == true);
280             int vi = jn.get<int>();
281             CHECK(vi == 42);
282 
283             // etc.
284         }
285 
286         {
287             // a JSON value
288             json j_original = R"({
289           "baz": ["one", "two", "three"],
290           "foo": "bar"
291         })"_json;
292 
293             // access members with a JSON pointer (RFC 6901)
294             j_original["/baz/1"_json_pointer];
295             // "two"
296 
297             // a JSON patch (RFC 6902)
298             json j_patch = R"([
299           { "op": "replace", "path": "/baz", "value": "boo" },
300           { "op": "add", "path": "/hello", "value": ["world"] },
301           { "op": "remove", "path": "/foo"}
302         ])"_json;
303 
304             // apply the patch
305             json j_result = j_original.patch(j_patch);
306             // {
307             //    "baz": "boo",
308             //    "hello": ["world"]
309             // }
310 
311             // calculate a JSON patch from two JSON values
312             auto res = json::diff(j_result, j_original);
313             // [
314             //   { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
315             //   { "op":"remove","path":"/hello" },
316             //   { "op":"add","path":"/foo","value":"bar" }
317             // ]
318         }
319 
320         // restore old std::cout
321         std::cout.rdbuf(old_cout_buffer);
322     }
323 }
324 
325 #if defined(_MSC_VER)
326     #pragma warning (pop)
327 #endif
328