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 <string> 31 #include <vector> 32 #include "doctest_compatibility.h" 33 34 #include <nlohmann/json.hpp> 35 using nlohmann::json; 36 37 namespace persons 38 { 39 class person_with_private_data 40 { 41 private: 42 std::string name = ""; 43 int age = 0; 44 json metadata = nullptr; 45 46 public: operator ==(const person_with_private_data & rhs) const47 bool operator==(const person_with_private_data& rhs) const 48 { 49 return name == rhs.name && age == rhs.age && metadata == rhs.metadata; 50 } 51 52 person_with_private_data() = default; person_with_private_data(std::string name_,int age_,json metadata_)53 person_with_private_data(std::string name_, int age_, json metadata_) 54 : name(std::move(name_)) 55 , age(age_) 56 , metadata(std::move(metadata_)) 57 {} 58 59 NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata) 60 }; 61 62 class person_without_private_data_1 63 { 64 public: 65 std::string name = ""; 66 int age = 0; 67 json metadata = nullptr; 68 operator ==(const person_without_private_data_1 & rhs) const69 bool operator==(const person_without_private_data_1& rhs) const 70 { 71 return name == rhs.name && age == rhs.age && metadata == rhs.metadata; 72 } 73 74 person_without_private_data_1() = default; person_without_private_data_1(std::string name_,int age_,json metadata_)75 person_without_private_data_1(std::string name_, int age_, json metadata_) 76 : name(std::move(name_)) 77 , age(age_) 78 , metadata(std::move(metadata_)) 79 {} 80 81 NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_without_private_data_1, age, name, metadata) 82 }; 83 84 class person_without_private_data_2 85 { 86 public: 87 std::string name = ""; 88 int age = 0; 89 json metadata = nullptr; 90 operator ==(const person_without_private_data_2 & rhs) const91 bool operator==(const person_without_private_data_2& rhs) const 92 { 93 return name == rhs.name && age == rhs.age && metadata == rhs.metadata; 94 } 95 96 person_without_private_data_2() = default; person_without_private_data_2(std::string name_,int age_,json metadata_)97 person_without_private_data_2(std::string name_, int age_, json metadata_) 98 : name(std::move(name_)) 99 , age(age_) 100 , metadata(std::move(metadata_)) 101 {} 102 }; 103 104 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata) 105 106 class person_with_private_alphabet 107 { 108 public: operator ==(const person_with_private_alphabet & other)109 bool operator==(const person_with_private_alphabet& other) 110 { 111 return a == other.a && 112 b == other.b && 113 c == other.c && 114 d == other.d && 115 e == other.e && 116 f == other.f && 117 g == other.g && 118 h == other.h && 119 i == other.i && 120 j == other.j && 121 k == other.k && 122 l == other.l && 123 m == other.m && 124 n == other.n && 125 o == other.o && 126 p == other.p && 127 q == other.q && 128 r == other.r && 129 s == other.s && 130 t == other.t && 131 u == other.u && 132 v == other.v && 133 w == other.w && 134 x == other.x && 135 y == other.y && 136 z == other.z; 137 } 138 139 private: 140 int a = 0; 141 int b = 0; 142 int c = 0; 143 int d = 0; 144 int e = 0; 145 int f = 0; 146 int g = 0; 147 int h = 0; 148 int i = 0; 149 int j = 0; 150 int k = 0; 151 int l = 0; 152 int m = 0; 153 int n = 0; 154 int o = 0; 155 int p = 0; 156 int q = 0; 157 int r = 0; 158 int s = 0; 159 int t = 0; 160 int u = 0; 161 int v = 0; 162 int w = 0; 163 int x = 0; 164 int y = 0; 165 int z = 0; 166 NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_alphabet, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) 167 }; 168 169 class person_with_public_alphabet 170 { 171 public: operator ==(const person_with_public_alphabet & other)172 bool operator==(const person_with_public_alphabet& other) 173 { 174 return a == other.a && 175 b == other.b && 176 c == other.c && 177 d == other.d && 178 e == other.e && 179 f == other.f && 180 g == other.g && 181 h == other.h && 182 i == other.i && 183 j == other.j && 184 k == other.k && 185 l == other.l && 186 m == other.m && 187 n == other.n && 188 o == other.o && 189 p == other.p && 190 q == other.q && 191 r == other.r && 192 s == other.s && 193 t == other.t && 194 u == other.u && 195 v == other.v && 196 w == other.w && 197 x == other.x && 198 y == other.y && 199 z == other.z; 200 } 201 202 int a = 0; 203 int b = 0; 204 int c = 0; 205 int d = 0; 206 int e = 0; 207 int f = 0; 208 int g = 0; 209 int h = 0; 210 int i = 0; 211 int j = 0; 212 int k = 0; 213 int l = 0; 214 int m = 0; 215 int n = 0; 216 int o = 0; 217 int p = 0; 218 int q = 0; 219 int r = 0; 220 int s = 0; 221 int t = 0; 222 int u = 0; 223 int v = 0; 224 int w = 0; 225 int x = 0; 226 int y = 0; 227 int z = 0; 228 }; 229 230 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_with_public_alphabet, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) 231 232 } // namespace persons 233 234 TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE", T, 235 persons::person_with_private_data, 236 persons::person_without_private_data_1, 237 persons::person_without_private_data_2) 238 { 239 SECTION("person") 240 { 241 // serialization 242 T p1("Erik", 1, {{"haircuts", 2}}); 243 CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}"); 244 245 // deserialization 246 auto p2 = json(p1).get<T>(); 247 CHECK(p2 == p1); 248 249 // roundtrip 250 CHECK(T(json(p1)) == p1); 251 CHECK(json(T(json(p1))) == json(p1)); 252 253 // check exception in case of missing field 254 json j = json(p1); 255 j.erase("age"); 256 CHECK_THROWS_WITH_AS(j.get<T>(), "[json.exception.out_of_range.403] key 'age' not found", json::out_of_range); 257 } 258 } 259 260 TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, 261 persons::person_with_private_alphabet, 262 persons::person_with_public_alphabet) 263 { 264 SECTION("alphabet") 265 { 266 { 267 T obj1; 268 nlohmann::json j = obj1; //via json object 269 T obj2; 270 j.get_to(obj2); 271 bool ok = (obj1 == obj2); 272 CHECK(ok); 273 } 274 275 { 276 T obj1; 277 nlohmann::json j1 = obj1; //via json string 278 std::string s = j1.dump(); 279 nlohmann::json j2 = nlohmann::json::parse(s); 280 T obj2; 281 j2.get_to(obj2); 282 bool ok = (obj1 == obj2); 283 CHECK(ok); 284 } 285 286 { 287 T obj1; 288 nlohmann::json j1 = obj1; //via msgpack 289 std::vector<uint8_t> buf = nlohmann::json::to_msgpack(j1); 290 nlohmann::json j2 = nlohmann::json::from_msgpack(buf); 291 T obj2; 292 j2.get_to(obj2); 293 bool ok = (obj1 == obj2); 294 CHECK(ok); 295 } 296 297 { 298 T obj1; 299 nlohmann::json j1 = obj1; //via bson 300 std::vector<uint8_t> buf = nlohmann::json::to_bson(j1); 301 nlohmann::json j2 = nlohmann::json::from_bson(buf); 302 T obj2; 303 j2.get_to(obj2); 304 bool ok = (obj1 == obj2); 305 CHECK(ok); 306 } 307 308 { 309 T obj1; 310 nlohmann::json j1 = obj1; //via cbor 311 std::vector<uint8_t> buf = nlohmann::json::to_cbor(j1); 312 nlohmann::json j2 = nlohmann::json::from_cbor(buf); 313 T obj2; 314 j2.get_to(obj2); 315 bool ok = (obj1 == obj2); 316 CHECK(ok); 317 } 318 319 { 320 T obj1; 321 nlohmann::json j1 = obj1; //via ubjson 322 std::vector<uint8_t> buf = nlohmann::json::to_ubjson(j1); 323 nlohmann::json j2 = nlohmann::json::from_ubjson(buf); 324 T obj2; 325 j2.get_to(obj2); 326 bool ok = (obj1 == obj2); 327 CHECK(ok); 328 } 329 } 330 } 331