1c5f01b2fSopenharmony_ci// __ _____ _____ _____ 2c5f01b2fSopenharmony_ci// __| | __| | | | JSON for Modern C++ (supporting code) 3c5f01b2fSopenharmony_ci// | | |__ | | | | | | version 3.11.2 4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5c5f01b2fSopenharmony_ci// 6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT 8c5f01b2fSopenharmony_ci 9c5f01b2fSopenharmony_ci#include "doctest_compatibility.h" 10c5f01b2fSopenharmony_ci 11c5f01b2fSopenharmony_ci// disable -Wnoexcept due to class Evil 12c5f01b2fSopenharmony_ciDOCTEST_GCC_SUPPRESS_WARNING_PUSH 13c5f01b2fSopenharmony_ciDOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") 14c5f01b2fSopenharmony_ci 15c5f01b2fSopenharmony_ci#include <nlohmann/json.hpp> 16c5f01b2fSopenharmony_ciusing nlohmann::json; 17c5f01b2fSopenharmony_ci#ifdef JSON_TEST_NO_GLOBAL_UDLS 18c5f01b2fSopenharmony_ci using namespace nlohmann::literals; // NOLINT(google-build-using-namespace) 19c5f01b2fSopenharmony_ci#endif 20c5f01b2fSopenharmony_ci 21c5f01b2fSopenharmony_ci#include <map> 22c5f01b2fSopenharmony_ci#include <memory> 23c5f01b2fSopenharmony_ci#include <string> 24c5f01b2fSopenharmony_ci#include <utility> 25c5f01b2fSopenharmony_ci 26c5f01b2fSopenharmony_cinamespace udt 27c5f01b2fSopenharmony_ci{ 28c5f01b2fSopenharmony_cienum class country 29c5f01b2fSopenharmony_ci{ 30c5f01b2fSopenharmony_ci china, 31c5f01b2fSopenharmony_ci france, 32c5f01b2fSopenharmony_ci russia 33c5f01b2fSopenharmony_ci}; 34c5f01b2fSopenharmony_ci 35c5f01b2fSopenharmony_cistruct age 36c5f01b2fSopenharmony_ci{ 37c5f01b2fSopenharmony_ci int m_val; 38c5f01b2fSopenharmony_ci age(int rhs = 0) : m_val(rhs) {} 39c5f01b2fSopenharmony_ci}; 40c5f01b2fSopenharmony_ci 41c5f01b2fSopenharmony_cistruct name 42c5f01b2fSopenharmony_ci{ 43c5f01b2fSopenharmony_ci std::string m_val; 44c5f01b2fSopenharmony_ci name(std::string rhs = "") : m_val(std::move(rhs)) {} 45c5f01b2fSopenharmony_ci}; 46c5f01b2fSopenharmony_ci 47c5f01b2fSopenharmony_cistruct address 48c5f01b2fSopenharmony_ci{ 49c5f01b2fSopenharmony_ci std::string m_val; 50c5f01b2fSopenharmony_ci address(std::string rhs = "") : m_val(std::move(rhs)) {} 51c5f01b2fSopenharmony_ci}; 52c5f01b2fSopenharmony_ci 53c5f01b2fSopenharmony_cistruct person 54c5f01b2fSopenharmony_ci{ 55c5f01b2fSopenharmony_ci age m_age{}; 56c5f01b2fSopenharmony_ci name m_name{}; 57c5f01b2fSopenharmony_ci country m_country{}; 58c5f01b2fSopenharmony_ci person() = default; 59c5f01b2fSopenharmony_ci person(const age& a, name n, const country& c) : m_age(a), m_name(std::move(n)), m_country(c) {} 60c5f01b2fSopenharmony_ci}; 61c5f01b2fSopenharmony_ci 62c5f01b2fSopenharmony_cistruct contact 63c5f01b2fSopenharmony_ci{ 64c5f01b2fSopenharmony_ci person m_person{}; 65c5f01b2fSopenharmony_ci address m_address{}; 66c5f01b2fSopenharmony_ci contact() = default; 67c5f01b2fSopenharmony_ci contact(person p, address a) : m_person(std::move(p)), m_address(std::move(a)) {} 68c5f01b2fSopenharmony_ci}; 69c5f01b2fSopenharmony_ci 70c5f01b2fSopenharmony_cistruct contact_book 71c5f01b2fSopenharmony_ci{ 72c5f01b2fSopenharmony_ci name m_book_name{}; 73c5f01b2fSopenharmony_ci std::vector<contact> m_contacts{}; 74c5f01b2fSopenharmony_ci contact_book() = default; 75c5f01b2fSopenharmony_ci contact_book(name n, std::vector<contact> c) : m_book_name(std::move(n)), m_contacts(std::move(c)) {} 76c5f01b2fSopenharmony_ci}; 77c5f01b2fSopenharmony_ci} // namespace udt 78c5f01b2fSopenharmony_ci 79c5f01b2fSopenharmony_ci// to_json methods 80c5f01b2fSopenharmony_cinamespace udt 81c5f01b2fSopenharmony_ci{ 82c5f01b2fSopenharmony_ci// templates because of the custom_json tests (see below) 83c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 84c5f01b2fSopenharmony_cistatic void to_json(BasicJsonType& j, age a) 85c5f01b2fSopenharmony_ci{ 86c5f01b2fSopenharmony_ci j = a.m_val; 87c5f01b2fSopenharmony_ci} 88c5f01b2fSopenharmony_ci 89c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 90c5f01b2fSopenharmony_cistatic void to_json(BasicJsonType& j, const name& n) 91c5f01b2fSopenharmony_ci{ 92c5f01b2fSopenharmony_ci j = n.m_val; 93c5f01b2fSopenharmony_ci} 94c5f01b2fSopenharmony_ci 95c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 96c5f01b2fSopenharmony_cistatic void to_json(BasicJsonType& j, country c) 97c5f01b2fSopenharmony_ci{ 98c5f01b2fSopenharmony_ci switch (c) 99c5f01b2fSopenharmony_ci { 100c5f01b2fSopenharmony_ci case country::china: 101c5f01b2fSopenharmony_ci j = "中华人民共和国"; 102c5f01b2fSopenharmony_ci return; 103c5f01b2fSopenharmony_ci case country::france: 104c5f01b2fSopenharmony_ci j = "France"; 105c5f01b2fSopenharmony_ci return; 106c5f01b2fSopenharmony_ci case country::russia: 107c5f01b2fSopenharmony_ci j = "Российская Федерация"; 108c5f01b2fSopenharmony_ci return; 109c5f01b2fSopenharmony_ci default: 110c5f01b2fSopenharmony_ci break; 111c5f01b2fSopenharmony_ci } 112c5f01b2fSopenharmony_ci} 113c5f01b2fSopenharmony_ci 114c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 115c5f01b2fSopenharmony_cistatic void to_json(BasicJsonType& j, const person& p) 116c5f01b2fSopenharmony_ci{ 117c5f01b2fSopenharmony_ci j = BasicJsonType{{"age", p.m_age}, {"name", p.m_name}, {"country", p.m_country}}; 118c5f01b2fSopenharmony_ci} 119c5f01b2fSopenharmony_ci 120c5f01b2fSopenharmony_cistatic void to_json(nlohmann::json& j, const address& a) 121c5f01b2fSopenharmony_ci{ 122c5f01b2fSopenharmony_ci j = a.m_val; 123c5f01b2fSopenharmony_ci} 124c5f01b2fSopenharmony_ci 125c5f01b2fSopenharmony_cistatic void to_json(nlohmann::json& j, const contact& c) 126c5f01b2fSopenharmony_ci{ 127c5f01b2fSopenharmony_ci j = json{{"person", c.m_person}, {"address", c.m_address}}; 128c5f01b2fSopenharmony_ci} 129c5f01b2fSopenharmony_ci 130c5f01b2fSopenharmony_cistatic void to_json(nlohmann::json& j, const contact_book& cb) 131c5f01b2fSopenharmony_ci{ 132c5f01b2fSopenharmony_ci j = json{{"name", cb.m_book_name}, {"contacts", cb.m_contacts}}; 133c5f01b2fSopenharmony_ci} 134c5f01b2fSopenharmony_ci 135c5f01b2fSopenharmony_ci// operators 136c5f01b2fSopenharmony_cistatic bool operator==(age lhs, age rhs) 137c5f01b2fSopenharmony_ci{ 138c5f01b2fSopenharmony_ci return lhs.m_val == rhs.m_val; 139c5f01b2fSopenharmony_ci} 140c5f01b2fSopenharmony_ci 141c5f01b2fSopenharmony_cistatic bool operator==(const address& lhs, const address& rhs) 142c5f01b2fSopenharmony_ci{ 143c5f01b2fSopenharmony_ci return lhs.m_val == rhs.m_val; 144c5f01b2fSopenharmony_ci} 145c5f01b2fSopenharmony_ci 146c5f01b2fSopenharmony_cistatic bool operator==(const name& lhs, const name& rhs) 147c5f01b2fSopenharmony_ci{ 148c5f01b2fSopenharmony_ci return lhs.m_val == rhs.m_val; 149c5f01b2fSopenharmony_ci} 150c5f01b2fSopenharmony_ci 151c5f01b2fSopenharmony_cistatic bool operator==(const person& lhs, const person& rhs) 152c5f01b2fSopenharmony_ci{ 153c5f01b2fSopenharmony_ci return std::tie(lhs.m_name, lhs.m_age) == std::tie(rhs.m_name, rhs.m_age); 154c5f01b2fSopenharmony_ci} 155c5f01b2fSopenharmony_ci 156c5f01b2fSopenharmony_cistatic bool operator==(const contact& lhs, const contact& rhs) 157c5f01b2fSopenharmony_ci{ 158c5f01b2fSopenharmony_ci return std::tie(lhs.m_person, lhs.m_address) == 159c5f01b2fSopenharmony_ci std::tie(rhs.m_person, rhs.m_address); 160c5f01b2fSopenharmony_ci} 161c5f01b2fSopenharmony_ci 162c5f01b2fSopenharmony_cistatic bool operator==(const contact_book& lhs, const contact_book& rhs) 163c5f01b2fSopenharmony_ci{ 164c5f01b2fSopenharmony_ci return std::tie(lhs.m_book_name, lhs.m_contacts) == 165c5f01b2fSopenharmony_ci std::tie(rhs.m_book_name, rhs.m_contacts); 166c5f01b2fSopenharmony_ci} 167c5f01b2fSopenharmony_ci} // namespace udt 168c5f01b2fSopenharmony_ci 169c5f01b2fSopenharmony_ci// from_json methods 170c5f01b2fSopenharmony_cinamespace udt 171c5f01b2fSopenharmony_ci{ 172c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 173c5f01b2fSopenharmony_cistatic void from_json(const BasicJsonType& j, age& a) 174c5f01b2fSopenharmony_ci{ 175c5f01b2fSopenharmony_ci a.m_val = j.template get<int>(); 176c5f01b2fSopenharmony_ci} 177c5f01b2fSopenharmony_ci 178c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 179c5f01b2fSopenharmony_cistatic void from_json(const BasicJsonType& j, name& n) 180c5f01b2fSopenharmony_ci{ 181c5f01b2fSopenharmony_ci n.m_val = j.template get<std::string>(); 182c5f01b2fSopenharmony_ci} 183c5f01b2fSopenharmony_ci 184c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 185c5f01b2fSopenharmony_cistatic void from_json(const BasicJsonType& j, country& c) 186c5f01b2fSopenharmony_ci{ 187c5f01b2fSopenharmony_ci const auto str = j.template get<std::string>(); 188c5f01b2fSopenharmony_ci const std::map<std::string, country> m = 189c5f01b2fSopenharmony_ci { 190c5f01b2fSopenharmony_ci {"中华人民共和国", country::china}, 191c5f01b2fSopenharmony_ci {"France", country::france}, 192c5f01b2fSopenharmony_ci {"Российская Федерация", country::russia} 193c5f01b2fSopenharmony_ci }; 194c5f01b2fSopenharmony_ci 195c5f01b2fSopenharmony_ci const auto it = m.find(str); 196c5f01b2fSopenharmony_ci // TODO(nlohmann) test exceptions 197c5f01b2fSopenharmony_ci c = it->second; 198c5f01b2fSopenharmony_ci} 199c5f01b2fSopenharmony_ci 200c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 201c5f01b2fSopenharmony_cistatic void from_json(const BasicJsonType& j, person& p) 202c5f01b2fSopenharmony_ci{ 203c5f01b2fSopenharmony_ci p.m_age = j["age"].template get<age>(); 204c5f01b2fSopenharmony_ci p.m_name = j["name"].template get<name>(); 205c5f01b2fSopenharmony_ci p.m_country = j["country"].template get<country>(); 206c5f01b2fSopenharmony_ci} 207c5f01b2fSopenharmony_ci 208c5f01b2fSopenharmony_cistatic void from_json(const nlohmann::json& j, address& a) 209c5f01b2fSopenharmony_ci{ 210c5f01b2fSopenharmony_ci a.m_val = j.get<std::string>(); 211c5f01b2fSopenharmony_ci} 212c5f01b2fSopenharmony_ci 213c5f01b2fSopenharmony_cistatic void from_json(const nlohmann::json& j, contact& c) 214c5f01b2fSopenharmony_ci{ 215c5f01b2fSopenharmony_ci c.m_person = j["person"].get<person>(); 216c5f01b2fSopenharmony_ci c.m_address = j["address"].get<address>(); 217c5f01b2fSopenharmony_ci} 218c5f01b2fSopenharmony_ci 219c5f01b2fSopenharmony_cistatic void from_json(const nlohmann::json& j, contact_book& cb) 220c5f01b2fSopenharmony_ci{ 221c5f01b2fSopenharmony_ci cb.m_book_name = j["name"].get<name>(); 222c5f01b2fSopenharmony_ci cb.m_contacts = j["contacts"].get<std::vector<contact>>(); 223c5f01b2fSopenharmony_ci} 224c5f01b2fSopenharmony_ci} // namespace udt 225c5f01b2fSopenharmony_ci 226c5f01b2fSopenharmony_ciTEST_CASE("basic usage" * doctest::test_suite("udt")) 227c5f01b2fSopenharmony_ci{ 228c5f01b2fSopenharmony_ci 229c5f01b2fSopenharmony_ci // a bit narcissistic maybe :) ? 230c5f01b2fSopenharmony_ci const udt::age a 231c5f01b2fSopenharmony_ci { 232c5f01b2fSopenharmony_ci 23 233c5f01b2fSopenharmony_ci }; 234c5f01b2fSopenharmony_ci const udt::name n{"theo"}; 235c5f01b2fSopenharmony_ci const udt::country c{udt::country::france}; 236c5f01b2fSopenharmony_ci const udt::person sfinae_addict{a, n, c}; 237c5f01b2fSopenharmony_ci const udt::person senior_programmer{{42}, {"王芳"}, udt::country::china}; 238c5f01b2fSopenharmony_ci const udt::address addr{"Paris"}; 239c5f01b2fSopenharmony_ci const udt::contact cpp_programmer{sfinae_addict, addr}; 240c5f01b2fSopenharmony_ci const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}}; 241c5f01b2fSopenharmony_ci 242c5f01b2fSopenharmony_ci SECTION("conversion to json via free-functions") 243c5f01b2fSopenharmony_ci { 244c5f01b2fSopenharmony_ci CHECK(json(a) == json(23)); 245c5f01b2fSopenharmony_ci CHECK(json(n) == json("theo")); 246c5f01b2fSopenharmony_ci CHECK(json(c) == json("France")); 247c5f01b2fSopenharmony_ci CHECK(json(sfinae_addict) == R"({"name":"theo", "age":23, "country":"France"})"_json); 248c5f01b2fSopenharmony_ci CHECK(json("Paris") == json(addr)); 249c5f01b2fSopenharmony_ci CHECK(json(cpp_programmer) == 250c5f01b2fSopenharmony_ci R"({"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"})"_json); 251c5f01b2fSopenharmony_ci 252c5f01b2fSopenharmony_ci CHECK( 253c5f01b2fSopenharmony_ci json(book) == 254c5f01b2fSopenharmony_ci R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); 255c5f01b2fSopenharmony_ci 256c5f01b2fSopenharmony_ci } 257c5f01b2fSopenharmony_ci 258c5f01b2fSopenharmony_ci SECTION("conversion from json via free-functions") 259c5f01b2fSopenharmony_ci { 260c5f01b2fSopenharmony_ci const auto big_json = 261c5f01b2fSopenharmony_ci R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; 262c5f01b2fSopenharmony_ci SECTION("via explicit calls to get") 263c5f01b2fSopenharmony_ci { 264c5f01b2fSopenharmony_ci const auto parsed_book = big_json.get<udt::contact_book>(); 265c5f01b2fSopenharmony_ci const auto book_name = big_json["name"].get<udt::name>(); 266c5f01b2fSopenharmony_ci const auto contacts = 267c5f01b2fSopenharmony_ci big_json["contacts"].get<std::vector<udt::contact>>(); 268c5f01b2fSopenharmony_ci const auto contact_json = big_json["contacts"].at(0); 269c5f01b2fSopenharmony_ci const auto contact = contact_json.get<udt::contact>(); 270c5f01b2fSopenharmony_ci const auto person = contact_json["person"].get<udt::person>(); 271c5f01b2fSopenharmony_ci const auto address = contact_json["address"].get<udt::address>(); 272c5f01b2fSopenharmony_ci const auto age = contact_json["person"]["age"].get<udt::age>(); 273c5f01b2fSopenharmony_ci const auto country = 274c5f01b2fSopenharmony_ci contact_json["person"]["country"].get<udt::country>(); 275c5f01b2fSopenharmony_ci const auto name = contact_json["person"]["name"].get<udt::name>(); 276c5f01b2fSopenharmony_ci 277c5f01b2fSopenharmony_ci CHECK(age == a); 278c5f01b2fSopenharmony_ci CHECK(name == n); 279c5f01b2fSopenharmony_ci CHECK(country == c); 280c5f01b2fSopenharmony_ci CHECK(address == addr); 281c5f01b2fSopenharmony_ci CHECK(person == sfinae_addict); 282c5f01b2fSopenharmony_ci CHECK(contact == cpp_programmer); 283c5f01b2fSopenharmony_ci CHECK(contacts == book.m_contacts); 284c5f01b2fSopenharmony_ci CHECK(book_name == udt::name{"C++"}); 285c5f01b2fSopenharmony_ci CHECK(book == parsed_book); 286c5f01b2fSopenharmony_ci } 287c5f01b2fSopenharmony_ci 288c5f01b2fSopenharmony_ci SECTION("via explicit calls to get_to") 289c5f01b2fSopenharmony_ci { 290c5f01b2fSopenharmony_ci udt::person person; 291c5f01b2fSopenharmony_ci udt::name name; 292c5f01b2fSopenharmony_ci 293c5f01b2fSopenharmony_ci json person_json = big_json["contacts"][0]["person"]; 294c5f01b2fSopenharmony_ci CHECK(person_json.get_to(person) == sfinae_addict); 295c5f01b2fSopenharmony_ci 296c5f01b2fSopenharmony_ci // correct reference gets returned 297c5f01b2fSopenharmony_ci person_json["name"].get_to(name).m_val = "new name"; 298c5f01b2fSopenharmony_ci CHECK(name.m_val == "new name"); 299c5f01b2fSopenharmony_ci } 300c5f01b2fSopenharmony_ci 301c5f01b2fSopenharmony_ci#if JSON_USE_IMPLICIT_CONVERSIONS 302c5f01b2fSopenharmony_ci SECTION("implicit conversions") 303c5f01b2fSopenharmony_ci { 304c5f01b2fSopenharmony_ci const udt::contact_book parsed_book = big_json; 305c5f01b2fSopenharmony_ci const udt::name book_name = big_json["name"]; 306c5f01b2fSopenharmony_ci const std::vector<udt::contact> contacts = big_json["contacts"]; 307c5f01b2fSopenharmony_ci const auto contact_json = big_json["contacts"].at(0); 308c5f01b2fSopenharmony_ci const udt::contact contact = contact_json; 309c5f01b2fSopenharmony_ci const udt::person person = contact_json["person"]; 310c5f01b2fSopenharmony_ci const udt::address address = contact_json["address"]; 311c5f01b2fSopenharmony_ci const udt::age age = contact_json["person"]["age"]; 312c5f01b2fSopenharmony_ci const udt::country country = contact_json["person"]["country"]; 313c5f01b2fSopenharmony_ci const udt::name name = contact_json["person"]["name"]; 314c5f01b2fSopenharmony_ci 315c5f01b2fSopenharmony_ci CHECK(age == a); 316c5f01b2fSopenharmony_ci CHECK(name == n); 317c5f01b2fSopenharmony_ci CHECK(country == c); 318c5f01b2fSopenharmony_ci CHECK(address == addr); 319c5f01b2fSopenharmony_ci CHECK(person == sfinae_addict); 320c5f01b2fSopenharmony_ci CHECK(contact == cpp_programmer); 321c5f01b2fSopenharmony_ci CHECK(contacts == book.m_contacts); 322c5f01b2fSopenharmony_ci CHECK(book_name == udt::name{"C++"}); 323c5f01b2fSopenharmony_ci CHECK(book == parsed_book); 324c5f01b2fSopenharmony_ci } 325c5f01b2fSopenharmony_ci#endif 326c5f01b2fSopenharmony_ci } 327c5f01b2fSopenharmony_ci} 328c5f01b2fSopenharmony_ci 329c5f01b2fSopenharmony_cinamespace udt 330c5f01b2fSopenharmony_ci{ 331c5f01b2fSopenharmony_cistruct legacy_type 332c5f01b2fSopenharmony_ci{ 333c5f01b2fSopenharmony_ci std::string number{}; 334c5f01b2fSopenharmony_ci legacy_type() = default; 335c5f01b2fSopenharmony_ci legacy_type(std::string n) : number(std::move(n)) {} 336c5f01b2fSopenharmony_ci}; 337c5f01b2fSopenharmony_ci} // namespace udt 338c5f01b2fSopenharmony_ci 339c5f01b2fSopenharmony_cinamespace nlohmann 340c5f01b2fSopenharmony_ci{ 341c5f01b2fSopenharmony_citemplate <typename T> 342c5f01b2fSopenharmony_cistruct adl_serializer<std::shared_ptr<T>> 343c5f01b2fSopenharmony_ci{ 344c5f01b2fSopenharmony_ci static void to_json(json& j, const std::shared_ptr<T>& opt) 345c5f01b2fSopenharmony_ci { 346c5f01b2fSopenharmony_ci if (opt) 347c5f01b2fSopenharmony_ci { 348c5f01b2fSopenharmony_ci j = *opt; 349c5f01b2fSopenharmony_ci } 350c5f01b2fSopenharmony_ci else 351c5f01b2fSopenharmony_ci { 352c5f01b2fSopenharmony_ci j = nullptr; 353c5f01b2fSopenharmony_ci } 354c5f01b2fSopenharmony_ci } 355c5f01b2fSopenharmony_ci 356c5f01b2fSopenharmony_ci static void from_json(const json& j, std::shared_ptr<T>& opt) 357c5f01b2fSopenharmony_ci { 358c5f01b2fSopenharmony_ci if (j.is_null()) 359c5f01b2fSopenharmony_ci { 360c5f01b2fSopenharmony_ci opt = nullptr; 361c5f01b2fSopenharmony_ci } 362c5f01b2fSopenharmony_ci else 363c5f01b2fSopenharmony_ci { 364c5f01b2fSopenharmony_ci opt.reset(new T(j.get<T>())); // NOLINT(cppcoreguidelines-owning-memory) 365c5f01b2fSopenharmony_ci } 366c5f01b2fSopenharmony_ci } 367c5f01b2fSopenharmony_ci}; 368c5f01b2fSopenharmony_ci 369c5f01b2fSopenharmony_citemplate <> 370c5f01b2fSopenharmony_cistruct adl_serializer<udt::legacy_type> 371c5f01b2fSopenharmony_ci{ 372c5f01b2fSopenharmony_ci static void to_json(json& j, const udt::legacy_type& l) 373c5f01b2fSopenharmony_ci { 374c5f01b2fSopenharmony_ci j = std::stoi(l.number); 375c5f01b2fSopenharmony_ci } 376c5f01b2fSopenharmony_ci 377c5f01b2fSopenharmony_ci static void from_json(const json& j, udt::legacy_type& l) 378c5f01b2fSopenharmony_ci { 379c5f01b2fSopenharmony_ci l.number = std::to_string(j.get<int>()); 380c5f01b2fSopenharmony_ci } 381c5f01b2fSopenharmony_ci}; 382c5f01b2fSopenharmony_ci} // namespace nlohmann 383c5f01b2fSopenharmony_ci 384c5f01b2fSopenharmony_ciTEST_CASE("adl_serializer specialization" * doctest::test_suite("udt")) 385c5f01b2fSopenharmony_ci{ 386c5f01b2fSopenharmony_ci SECTION("partial specialization") 387c5f01b2fSopenharmony_ci { 388c5f01b2fSopenharmony_ci SECTION("to_json") 389c5f01b2fSopenharmony_ci { 390c5f01b2fSopenharmony_ci std::shared_ptr<udt::person> optPerson; 391c5f01b2fSopenharmony_ci 392c5f01b2fSopenharmony_ci json j = optPerson; 393c5f01b2fSopenharmony_ci CHECK(j.is_null()); 394c5f01b2fSopenharmony_ci 395c5f01b2fSopenharmony_ci optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-shared) 396c5f01b2fSopenharmony_ci j = optPerson; 397c5f01b2fSopenharmony_ci CHECK_FALSE(j.is_null()); 398c5f01b2fSopenharmony_ci 399c5f01b2fSopenharmony_ci CHECK(j.get<udt::person>() == *optPerson); 400c5f01b2fSopenharmony_ci } 401c5f01b2fSopenharmony_ci 402c5f01b2fSopenharmony_ci SECTION("from_json") 403c5f01b2fSopenharmony_ci { 404c5f01b2fSopenharmony_ci auto person = udt::person{{42}, {"John Doe"}, udt::country::russia}; 405c5f01b2fSopenharmony_ci json j = person; 406c5f01b2fSopenharmony_ci 407c5f01b2fSopenharmony_ci auto optPerson = j.get<std::shared_ptr<udt::person>>(); 408c5f01b2fSopenharmony_ci REQUIRE(optPerson); 409c5f01b2fSopenharmony_ci CHECK(*optPerson == person); 410c5f01b2fSopenharmony_ci 411c5f01b2fSopenharmony_ci j = nullptr; 412c5f01b2fSopenharmony_ci optPerson = j.get<std::shared_ptr<udt::person>>(); 413c5f01b2fSopenharmony_ci CHECK(!optPerson); 414c5f01b2fSopenharmony_ci } 415c5f01b2fSopenharmony_ci } 416c5f01b2fSopenharmony_ci 417c5f01b2fSopenharmony_ci SECTION("total specialization") 418c5f01b2fSopenharmony_ci { 419c5f01b2fSopenharmony_ci SECTION("to_json") 420c5f01b2fSopenharmony_ci { 421c5f01b2fSopenharmony_ci udt::legacy_type lt{"4242"}; 422c5f01b2fSopenharmony_ci 423c5f01b2fSopenharmony_ci json j = lt; 424c5f01b2fSopenharmony_ci CHECK(j.get<int>() == 4242); 425c5f01b2fSopenharmony_ci } 426c5f01b2fSopenharmony_ci 427c5f01b2fSopenharmony_ci SECTION("from_json") 428c5f01b2fSopenharmony_ci { 429c5f01b2fSopenharmony_ci json j = 4242; 430c5f01b2fSopenharmony_ci auto lt = j.get<udt::legacy_type>(); 431c5f01b2fSopenharmony_ci CHECK(lt.number == "4242"); 432c5f01b2fSopenharmony_ci } 433c5f01b2fSopenharmony_ci } 434c5f01b2fSopenharmony_ci} 435c5f01b2fSopenharmony_ci 436c5f01b2fSopenharmony_cinamespace nlohmann 437c5f01b2fSopenharmony_ci{ 438c5f01b2fSopenharmony_citemplate <> 439c5f01b2fSopenharmony_cistruct adl_serializer<std::vector<float>> 440c5f01b2fSopenharmony_ci{ 441c5f01b2fSopenharmony_ci using type = std::vector<float>; 442c5f01b2fSopenharmony_ci static void to_json(json& j, const type& /*type*/) 443c5f01b2fSopenharmony_ci { 444c5f01b2fSopenharmony_ci j = "hijacked!"; 445c5f01b2fSopenharmony_ci } 446c5f01b2fSopenharmony_ci 447c5f01b2fSopenharmony_ci static void from_json(const json& /*unnamed*/, type& opt) 448c5f01b2fSopenharmony_ci { 449c5f01b2fSopenharmony_ci opt = {42.0, 42.0, 42.0}; 450c5f01b2fSopenharmony_ci } 451c5f01b2fSopenharmony_ci 452c5f01b2fSopenharmony_ci // preferred version 453c5f01b2fSopenharmony_ci static type from_json(const json& /*unnamed*/) 454c5f01b2fSopenharmony_ci { 455c5f01b2fSopenharmony_ci return {4.0, 5.0, 6.0}; 456c5f01b2fSopenharmony_ci } 457c5f01b2fSopenharmony_ci}; 458c5f01b2fSopenharmony_ci} // namespace nlohmann 459c5f01b2fSopenharmony_ci 460c5f01b2fSopenharmony_ciTEST_CASE("even supported types can be specialized" * doctest::test_suite("udt")) 461c5f01b2fSopenharmony_ci{ 462c5f01b2fSopenharmony_ci json j = std::vector<float> {1.0, 2.0, 3.0}; 463c5f01b2fSopenharmony_ci CHECK(j.dump() == R"("hijacked!")"); 464c5f01b2fSopenharmony_ci auto f = j.get<std::vector<float>>(); 465c5f01b2fSopenharmony_ci // the single argument from_json method is preferred 466c5f01b2fSopenharmony_ci CHECK((f == std::vector<float> {4.0, 5.0, 6.0})); 467c5f01b2fSopenharmony_ci} 468c5f01b2fSopenharmony_ci 469c5f01b2fSopenharmony_cinamespace nlohmann 470c5f01b2fSopenharmony_ci{ 471c5f01b2fSopenharmony_citemplate <typename T> 472c5f01b2fSopenharmony_cistruct adl_serializer<std::unique_ptr<T>> 473c5f01b2fSopenharmony_ci{ 474c5f01b2fSopenharmony_ci static void to_json(json& j, const std::unique_ptr<T>& opt) 475c5f01b2fSopenharmony_ci { 476c5f01b2fSopenharmony_ci if (opt) 477c5f01b2fSopenharmony_ci { 478c5f01b2fSopenharmony_ci j = *opt; 479c5f01b2fSopenharmony_ci } 480c5f01b2fSopenharmony_ci else 481c5f01b2fSopenharmony_ci { 482c5f01b2fSopenharmony_ci j = nullptr; 483c5f01b2fSopenharmony_ci } 484c5f01b2fSopenharmony_ci } 485c5f01b2fSopenharmony_ci 486c5f01b2fSopenharmony_ci // this is the overload needed for non-copyable types, 487c5f01b2fSopenharmony_ci static std::unique_ptr<T> from_json(const json& j) 488c5f01b2fSopenharmony_ci { 489c5f01b2fSopenharmony_ci if (j.is_null()) 490c5f01b2fSopenharmony_ci { 491c5f01b2fSopenharmony_ci return nullptr; 492c5f01b2fSopenharmony_ci } 493c5f01b2fSopenharmony_ci 494c5f01b2fSopenharmony_ci return std::unique_ptr<T>(new T(j.get<T>())); 495c5f01b2fSopenharmony_ci } 496c5f01b2fSopenharmony_ci}; 497c5f01b2fSopenharmony_ci} // namespace nlohmann 498c5f01b2fSopenharmony_ci 499c5f01b2fSopenharmony_ciTEST_CASE("Non-copyable types" * doctest::test_suite("udt")) 500c5f01b2fSopenharmony_ci{ 501c5f01b2fSopenharmony_ci SECTION("to_json") 502c5f01b2fSopenharmony_ci { 503c5f01b2fSopenharmony_ci std::unique_ptr<udt::person> optPerson; 504c5f01b2fSopenharmony_ci 505c5f01b2fSopenharmony_ci json j = optPerson; 506c5f01b2fSopenharmony_ci CHECK(j.is_null()); 507c5f01b2fSopenharmony_ci 508c5f01b2fSopenharmony_ci optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-unique) 509c5f01b2fSopenharmony_ci j = optPerson; 510c5f01b2fSopenharmony_ci CHECK_FALSE(j.is_null()); 511c5f01b2fSopenharmony_ci 512c5f01b2fSopenharmony_ci CHECK(j.get<udt::person>() == *optPerson); 513c5f01b2fSopenharmony_ci } 514c5f01b2fSopenharmony_ci 515c5f01b2fSopenharmony_ci SECTION("from_json") 516c5f01b2fSopenharmony_ci { 517c5f01b2fSopenharmony_ci auto person = udt::person{{42}, {"John Doe"}, udt::country::russia}; 518c5f01b2fSopenharmony_ci json j = person; 519c5f01b2fSopenharmony_ci 520c5f01b2fSopenharmony_ci auto optPerson = j.get<std::unique_ptr<udt::person>>(); 521c5f01b2fSopenharmony_ci REQUIRE(optPerson); 522c5f01b2fSopenharmony_ci CHECK(*optPerson == person); 523c5f01b2fSopenharmony_ci 524c5f01b2fSopenharmony_ci j = nullptr; 525c5f01b2fSopenharmony_ci optPerson = j.get<std::unique_ptr<udt::person>>(); 526c5f01b2fSopenharmony_ci CHECK(!optPerson); 527c5f01b2fSopenharmony_ci } 528c5f01b2fSopenharmony_ci} 529c5f01b2fSopenharmony_ci 530c5f01b2fSopenharmony_ci// custom serializer - advanced usage 531c5f01b2fSopenharmony_ci// pack structs that are pod-types (but not scalar types) 532c5f01b2fSopenharmony_ci// relies on adl for any other type 533c5f01b2fSopenharmony_citemplate <typename T, typename = void> 534c5f01b2fSopenharmony_cistruct pod_serializer 535c5f01b2fSopenharmony_ci{ 536c5f01b2fSopenharmony_ci // use adl for non-pods, or scalar types 537c5f01b2fSopenharmony_ci template < 538c5f01b2fSopenharmony_ci typename BasicJsonType, typename U = T, 539c5f01b2fSopenharmony_ci typename std::enable_if < 540c5f01b2fSopenharmony_ci !(std::is_pod<U>::value && std::is_class<U>::value), int >::type = 0 > 541c5f01b2fSopenharmony_ci static void from_json(const BasicJsonType& j, U& t) 542c5f01b2fSopenharmony_ci { 543c5f01b2fSopenharmony_ci using nlohmann::from_json; 544c5f01b2fSopenharmony_ci from_json(j, t); 545c5f01b2fSopenharmony_ci } 546c5f01b2fSopenharmony_ci 547c5f01b2fSopenharmony_ci // special behaviour for pods 548c5f01b2fSopenharmony_ci template < typename BasicJsonType, typename U = T, 549c5f01b2fSopenharmony_ci typename std::enable_if < 550c5f01b2fSopenharmony_ci std::is_pod<U>::value && std::is_class<U>::value, int >::type = 0 > 551c5f01b2fSopenharmony_ci static void from_json(const BasicJsonType& j, U& t) 552c5f01b2fSopenharmony_ci { 553c5f01b2fSopenharmony_ci std::uint64_t value = 0; 554c5f01b2fSopenharmony_ci // The following block is no longer relevant in this serializer, make another one that shows the issue 555c5f01b2fSopenharmony_ci // the problem arises only when one from_json method is defined without any constraint 556c5f01b2fSopenharmony_ci // 557c5f01b2fSopenharmony_ci // Why cannot we simply use: j.get<std::uint64_t>() ? 558c5f01b2fSopenharmony_ci // Well, with the current experiment, the get method looks for a from_json 559c5f01b2fSopenharmony_ci // function, which we are currently defining! 560c5f01b2fSopenharmony_ci // This would end up in a stack overflow. Calling nlohmann::from_json is a 561c5f01b2fSopenharmony_ci // workaround (is it?). 562c5f01b2fSopenharmony_ci // I shall find a good way to avoid this once all constructors are converted 563c5f01b2fSopenharmony_ci // to free methods 564c5f01b2fSopenharmony_ci // 565c5f01b2fSopenharmony_ci // In short, constructing a json by constructor calls to_json 566c5f01b2fSopenharmony_ci // calling get calls from_json, for now, we cannot do this in custom 567c5f01b2fSopenharmony_ci // serializers 568c5f01b2fSopenharmony_ci nlohmann::from_json(j, value); 569c5f01b2fSopenharmony_ci auto* bytes = static_cast<char*>(static_cast<void*>(&value)); 570c5f01b2fSopenharmony_ci std::memcpy(&t, bytes, sizeof(value)); 571c5f01b2fSopenharmony_ci } 572c5f01b2fSopenharmony_ci 573c5f01b2fSopenharmony_ci template < 574c5f01b2fSopenharmony_ci typename BasicJsonType, typename U = T, 575c5f01b2fSopenharmony_ci typename std::enable_if < 576c5f01b2fSopenharmony_ci !(std::is_pod<U>::value && std::is_class<U>::value), int >::type = 0 > 577c5f01b2fSopenharmony_ci static void to_json(BasicJsonType& j, const T& t) 578c5f01b2fSopenharmony_ci { 579c5f01b2fSopenharmony_ci using nlohmann::to_json; 580c5f01b2fSopenharmony_ci to_json(j, t); 581c5f01b2fSopenharmony_ci } 582c5f01b2fSopenharmony_ci 583c5f01b2fSopenharmony_ci template < typename BasicJsonType, typename U = T, 584c5f01b2fSopenharmony_ci typename std::enable_if < 585c5f01b2fSopenharmony_ci std::is_pod<U>::value && std::is_class<U>::value, int >::type = 0 > 586c5f01b2fSopenharmony_ci static void to_json(BasicJsonType& j, const T& t) noexcept 587c5f01b2fSopenharmony_ci { 588c5f01b2fSopenharmony_ci const auto* bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t)); 589c5f01b2fSopenharmony_ci std::uint64_t value = 0; 590c5f01b2fSopenharmony_ci std::memcpy(&value, bytes, sizeof(value)); 591c5f01b2fSopenharmony_ci nlohmann::to_json(j, value); 592c5f01b2fSopenharmony_ci } 593c5f01b2fSopenharmony_ci}; 594c5f01b2fSopenharmony_ci 595c5f01b2fSopenharmony_cinamespace udt 596c5f01b2fSopenharmony_ci{ 597c5f01b2fSopenharmony_cistruct small_pod 598c5f01b2fSopenharmony_ci{ 599c5f01b2fSopenharmony_ci int begin; 600c5f01b2fSopenharmony_ci char middle; 601c5f01b2fSopenharmony_ci short end; 602c5f01b2fSopenharmony_ci}; 603c5f01b2fSopenharmony_ci 604c5f01b2fSopenharmony_cistruct non_pod 605c5f01b2fSopenharmony_ci{ 606c5f01b2fSopenharmony_ci std::string s{}; 607c5f01b2fSopenharmony_ci non_pod() = default; 608c5f01b2fSopenharmony_ci non_pod(std::string S) : s(std::move(S)) {} 609c5f01b2fSopenharmony_ci}; 610c5f01b2fSopenharmony_ci 611c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 612c5f01b2fSopenharmony_cistatic void to_json(BasicJsonType& j, const non_pod& np) 613c5f01b2fSopenharmony_ci{ 614c5f01b2fSopenharmony_ci j = np.s; 615c5f01b2fSopenharmony_ci} 616c5f01b2fSopenharmony_ci 617c5f01b2fSopenharmony_citemplate <typename BasicJsonType> 618c5f01b2fSopenharmony_cistatic void from_json(const BasicJsonType& j, non_pod& np) 619c5f01b2fSopenharmony_ci{ 620c5f01b2fSopenharmony_ci np.s = j.template get<std::string>(); 621c5f01b2fSopenharmony_ci} 622c5f01b2fSopenharmony_ci 623c5f01b2fSopenharmony_cistatic bool operator==(small_pod lhs, small_pod rhs) noexcept 624c5f01b2fSopenharmony_ci{ 625c5f01b2fSopenharmony_ci return std::tie(lhs.begin, lhs.middle, lhs.end) == 626c5f01b2fSopenharmony_ci std::tie(rhs.begin, rhs.middle, rhs.end); 627c5f01b2fSopenharmony_ci} 628c5f01b2fSopenharmony_ci 629c5f01b2fSopenharmony_cistatic bool operator==(const non_pod& lhs, const non_pod& rhs) noexcept 630c5f01b2fSopenharmony_ci{ 631c5f01b2fSopenharmony_ci return lhs.s == rhs.s; 632c5f01b2fSopenharmony_ci} 633c5f01b2fSopenharmony_ci 634c5f01b2fSopenharmony_cistatic std::ostream& operator<<(std::ostream& os, small_pod l) 635c5f01b2fSopenharmony_ci{ 636c5f01b2fSopenharmony_ci return os << "begin: " << l.begin << ", middle: " << l.middle << ", end: " << l.end; 637c5f01b2fSopenharmony_ci} 638c5f01b2fSopenharmony_ci} // namespace udt 639c5f01b2fSopenharmony_ci 640c5f01b2fSopenharmony_ciTEST_CASE("custom serializer for pods" * doctest::test_suite("udt")) 641c5f01b2fSopenharmony_ci{ 642c5f01b2fSopenharmony_ci using custom_json = 643c5f01b2fSopenharmony_ci nlohmann::basic_json<std::map, std::vector, std::string, bool, 644c5f01b2fSopenharmony_ci std::int64_t, std::uint64_t, double, std::allocator, pod_serializer>; 645c5f01b2fSopenharmony_ci 646c5f01b2fSopenharmony_ci auto p = udt::small_pod{42, '/', 42}; 647c5f01b2fSopenharmony_ci custom_json j = p; 648c5f01b2fSopenharmony_ci 649c5f01b2fSopenharmony_ci auto p2 = j.get<udt::small_pod>(); 650c5f01b2fSopenharmony_ci 651c5f01b2fSopenharmony_ci CHECK(p == p2); 652c5f01b2fSopenharmony_ci 653c5f01b2fSopenharmony_ci auto np = udt::non_pod{{"non-pod"}}; 654c5f01b2fSopenharmony_ci custom_json j2 = np; 655c5f01b2fSopenharmony_ci auto np2 = j2.get<udt::non_pod>(); 656c5f01b2fSopenharmony_ci CHECK(np == np2); 657c5f01b2fSopenharmony_ci} 658c5f01b2fSopenharmony_ci 659c5f01b2fSopenharmony_citemplate <typename T, typename> 660c5f01b2fSopenharmony_cistruct another_adl_serializer; 661c5f01b2fSopenharmony_ci 662c5f01b2fSopenharmony_ciusing custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator, another_adl_serializer>; 663c5f01b2fSopenharmony_ci 664c5f01b2fSopenharmony_citemplate <typename T, typename> 665c5f01b2fSopenharmony_cistruct another_adl_serializer 666c5f01b2fSopenharmony_ci{ 667c5f01b2fSopenharmony_ci static void from_json(const custom_json& j, T& t) 668c5f01b2fSopenharmony_ci { 669c5f01b2fSopenharmony_ci using nlohmann::from_json; 670c5f01b2fSopenharmony_ci from_json(j, t); 671c5f01b2fSopenharmony_ci } 672c5f01b2fSopenharmony_ci 673c5f01b2fSopenharmony_ci static void to_json(custom_json& j, const T& t) 674c5f01b2fSopenharmony_ci { 675c5f01b2fSopenharmony_ci using nlohmann::to_json; 676c5f01b2fSopenharmony_ci to_json(j, t); 677c5f01b2fSopenharmony_ci } 678c5f01b2fSopenharmony_ci}; 679c5f01b2fSopenharmony_ci 680c5f01b2fSopenharmony_ciTEST_CASE("custom serializer that does adl by default" * doctest::test_suite("udt")) 681c5f01b2fSopenharmony_ci{ 682c5f01b2fSopenharmony_ci auto me = udt::person{{23}, {"theo"}, udt::country::france}; 683c5f01b2fSopenharmony_ci 684c5f01b2fSopenharmony_ci json j = me; 685c5f01b2fSopenharmony_ci custom_json cj = me; 686c5f01b2fSopenharmony_ci 687c5f01b2fSopenharmony_ci CHECK(j.dump() == cj.dump()); 688c5f01b2fSopenharmony_ci 689c5f01b2fSopenharmony_ci CHECK(me == j.get<udt::person>()); 690c5f01b2fSopenharmony_ci CHECK(me == cj.get<udt::person>()); 691c5f01b2fSopenharmony_ci} 692c5f01b2fSopenharmony_ci 693c5f01b2fSopenharmony_ciTEST_CASE("different basic_json types conversions") 694c5f01b2fSopenharmony_ci{ 695c5f01b2fSopenharmony_ci SECTION("null") 696c5f01b2fSopenharmony_ci { 697c5f01b2fSopenharmony_ci json j; 698c5f01b2fSopenharmony_ci custom_json cj = j; 699c5f01b2fSopenharmony_ci CHECK(cj == nullptr); 700c5f01b2fSopenharmony_ci } 701c5f01b2fSopenharmony_ci 702c5f01b2fSopenharmony_ci SECTION("boolean") 703c5f01b2fSopenharmony_ci { 704c5f01b2fSopenharmony_ci json j = true; 705c5f01b2fSopenharmony_ci custom_json cj = j; 706c5f01b2fSopenharmony_ci CHECK(cj == true); 707c5f01b2fSopenharmony_ci } 708c5f01b2fSopenharmony_ci 709c5f01b2fSopenharmony_ci SECTION("discarded") 710c5f01b2fSopenharmony_ci { 711c5f01b2fSopenharmony_ci json j(json::value_t::discarded); 712c5f01b2fSopenharmony_ci custom_json cj; 713c5f01b2fSopenharmony_ci CHECK_NOTHROW(cj = j); 714c5f01b2fSopenharmony_ci CHECK(cj.type() == custom_json::value_t::discarded); 715c5f01b2fSopenharmony_ci } 716c5f01b2fSopenharmony_ci 717c5f01b2fSopenharmony_ci SECTION("array") 718c5f01b2fSopenharmony_ci { 719c5f01b2fSopenharmony_ci json j = {1, 2, 3}; 720c5f01b2fSopenharmony_ci custom_json cj = j; 721c5f01b2fSopenharmony_ci CHECK((cj == std::vector<int> {1, 2, 3})); 722c5f01b2fSopenharmony_ci } 723c5f01b2fSopenharmony_ci 724c5f01b2fSopenharmony_ci SECTION("integer") 725c5f01b2fSopenharmony_ci { 726c5f01b2fSopenharmony_ci json j = 42; 727c5f01b2fSopenharmony_ci custom_json cj = j; 728c5f01b2fSopenharmony_ci CHECK(cj == 42); 729c5f01b2fSopenharmony_ci } 730c5f01b2fSopenharmony_ci 731c5f01b2fSopenharmony_ci SECTION("float") 732c5f01b2fSopenharmony_ci { 733c5f01b2fSopenharmony_ci json j = 42.0; 734c5f01b2fSopenharmony_ci custom_json cj = j; 735c5f01b2fSopenharmony_ci CHECK(cj == 42.0); 736c5f01b2fSopenharmony_ci } 737c5f01b2fSopenharmony_ci 738c5f01b2fSopenharmony_ci SECTION("unsigned") 739c5f01b2fSopenharmony_ci { 740c5f01b2fSopenharmony_ci json j = 42u; 741c5f01b2fSopenharmony_ci custom_json cj = j; 742c5f01b2fSopenharmony_ci CHECK(cj == 42u); 743c5f01b2fSopenharmony_ci } 744c5f01b2fSopenharmony_ci 745c5f01b2fSopenharmony_ci SECTION("string") 746c5f01b2fSopenharmony_ci { 747c5f01b2fSopenharmony_ci json j = "forty-two"; 748c5f01b2fSopenharmony_ci custom_json cj = j; 749c5f01b2fSopenharmony_ci CHECK(cj == "forty-two"); 750c5f01b2fSopenharmony_ci } 751c5f01b2fSopenharmony_ci 752c5f01b2fSopenharmony_ci SECTION("binary") 753c5f01b2fSopenharmony_ci { 754c5f01b2fSopenharmony_ci json j = json::binary({1, 2, 3}, 42); 755c5f01b2fSopenharmony_ci custom_json cj = j; 756c5f01b2fSopenharmony_ci CHECK(cj.get_binary().subtype() == 42); 757c5f01b2fSopenharmony_ci std::vector<std::uint8_t> cv = cj.get_binary(); 758c5f01b2fSopenharmony_ci std::vector<std::uint8_t> v = j.get_binary(); 759c5f01b2fSopenharmony_ci CHECK(cv == v); 760c5f01b2fSopenharmony_ci } 761c5f01b2fSopenharmony_ci 762c5f01b2fSopenharmony_ci SECTION("object") 763c5f01b2fSopenharmony_ci { 764c5f01b2fSopenharmony_ci json j = {{"forty", "two"}}; 765c5f01b2fSopenharmony_ci custom_json cj = j; 766c5f01b2fSopenharmony_ci auto m = j.get<std::map<std::string, std::string>>(); 767c5f01b2fSopenharmony_ci CHECK(cj == m); 768c5f01b2fSopenharmony_ci } 769c5f01b2fSopenharmony_ci 770c5f01b2fSopenharmony_ci SECTION("get<custom_json>") 771c5f01b2fSopenharmony_ci { 772c5f01b2fSopenharmony_ci json j = 42; 773c5f01b2fSopenharmony_ci custom_json cj = j.get<custom_json>(); 774c5f01b2fSopenharmony_ci CHECK(cj == 42); 775c5f01b2fSopenharmony_ci } 776c5f01b2fSopenharmony_ci} 777c5f01b2fSopenharmony_ci 778c5f01b2fSopenharmony_cinamespace 779c5f01b2fSopenharmony_ci{ 780c5f01b2fSopenharmony_cistruct incomplete; 781c5f01b2fSopenharmony_ci 782c5f01b2fSopenharmony_ci// std::is_constructible is broken on macOS' libc++ 783c5f01b2fSopenharmony_ci// use the cppreference implementation 784c5f01b2fSopenharmony_ci 785c5f01b2fSopenharmony_citemplate <typename T, typename = void> 786c5f01b2fSopenharmony_cistruct is_constructible_patched : std::false_type {}; 787c5f01b2fSopenharmony_ci 788c5f01b2fSopenharmony_citemplate <typename T> 789c5f01b2fSopenharmony_cistruct is_constructible_patched<T, decltype(void(json(std::declval<T>())))> : std::true_type {}; 790c5f01b2fSopenharmony_ci} // namespace 791c5f01b2fSopenharmony_ci 792c5f01b2fSopenharmony_ciTEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated context" * doctest::test_suite("udt")) 793c5f01b2fSopenharmony_ci{ 794c5f01b2fSopenharmony_ci static_assert(!is_constructible_patched<json, incomplete>::value, ""); 795c5f01b2fSopenharmony_ci} 796c5f01b2fSopenharmony_ci 797c5f01b2fSopenharmony_cinamespace 798c5f01b2fSopenharmony_ci{ 799c5f01b2fSopenharmony_ciclass Evil 800c5f01b2fSopenharmony_ci{ 801c5f01b2fSopenharmony_ci public: 802c5f01b2fSopenharmony_ci Evil() = default; 803c5f01b2fSopenharmony_ci template <typename T> 804c5f01b2fSopenharmony_ci Evil(T t) : m_i(sizeof(t)) 805c5f01b2fSopenharmony_ci { 806c5f01b2fSopenharmony_ci static_cast<void>(t); // fix MSVC's C4100 warning 807c5f01b2fSopenharmony_ci } 808c5f01b2fSopenharmony_ci 809c5f01b2fSopenharmony_ci int m_i = 0; 810c5f01b2fSopenharmony_ci}; 811c5f01b2fSopenharmony_ci 812c5f01b2fSopenharmony_civoid from_json(const json& /*unused*/, Evil& /*unused*/) {} 813c5f01b2fSopenharmony_ci} // namespace 814c5f01b2fSopenharmony_ci 815c5f01b2fSopenharmony_ciTEST_CASE("Issue #924") 816c5f01b2fSopenharmony_ci{ 817c5f01b2fSopenharmony_ci // Prevent get<std::vector<Evil>>() to throw 818c5f01b2fSopenharmony_ci auto j = json::array(); 819c5f01b2fSopenharmony_ci 820c5f01b2fSopenharmony_ci CHECK_NOTHROW(j.get<Evil>()); 821c5f01b2fSopenharmony_ci CHECK_NOTHROW(j.get<std::vector<Evil>>()); 822c5f01b2fSopenharmony_ci 823c5f01b2fSopenharmony_ci // silence Wunused-template warnings 824c5f01b2fSopenharmony_ci Evil e(1); 825c5f01b2fSopenharmony_ci CHECK(e.m_i >= 0); 826c5f01b2fSopenharmony_ci} 827c5f01b2fSopenharmony_ci 828c5f01b2fSopenharmony_ciTEST_CASE("Issue #1237") 829c5f01b2fSopenharmony_ci{ 830c5f01b2fSopenharmony_ci struct non_convertible_type {}; 831c5f01b2fSopenharmony_ci static_assert(!std::is_convertible<json, non_convertible_type>::value, ""); 832c5f01b2fSopenharmony_ci} 833c5f01b2fSopenharmony_ci 834c5f01b2fSopenharmony_cinamespace 835c5f01b2fSopenharmony_ci{ 836c5f01b2fSopenharmony_ciclass no_iterator_type 837c5f01b2fSopenharmony_ci{ 838c5f01b2fSopenharmony_ci public: 839c5f01b2fSopenharmony_ci no_iterator_type(std::initializer_list<int> l) 840c5f01b2fSopenharmony_ci : _v(l) 841c5f01b2fSopenharmony_ci {} 842c5f01b2fSopenharmony_ci 843c5f01b2fSopenharmony_ci std::vector<int>::const_iterator begin() const 844c5f01b2fSopenharmony_ci { 845c5f01b2fSopenharmony_ci return _v.begin(); 846c5f01b2fSopenharmony_ci } 847c5f01b2fSopenharmony_ci 848c5f01b2fSopenharmony_ci std::vector<int>::const_iterator end() const 849c5f01b2fSopenharmony_ci { 850c5f01b2fSopenharmony_ci return _v.end(); 851c5f01b2fSopenharmony_ci } 852c5f01b2fSopenharmony_ci 853c5f01b2fSopenharmony_ci private: 854c5f01b2fSopenharmony_ci std::vector<int> _v; 855c5f01b2fSopenharmony_ci}; 856c5f01b2fSopenharmony_ci} // namespace 857c5f01b2fSopenharmony_ci 858c5f01b2fSopenharmony_ciTEST_CASE("compatible array type, without iterator type alias") 859c5f01b2fSopenharmony_ci{ 860c5f01b2fSopenharmony_ci no_iterator_type vec{1, 2, 3}; 861c5f01b2fSopenharmony_ci json j = vec; 862c5f01b2fSopenharmony_ci} 863c5f01b2fSopenharmony_ci 864c5f01b2fSopenharmony_ciDOCTEST_GCC_SUPPRESS_WARNING_POP 865