mirror of
https://github.com/nlohmann/json.git
synced 2026-05-03 12:55:23 +00:00
🎨 use Clang-Format
This commit is contained in:
+113
-106
@@ -15,7 +15,7 @@ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
@@ -23,8 +23,7 @@ using nlohmann::json;
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace udt
|
||||
{
|
||||
namespace udt {
|
||||
enum class country
|
||||
{
|
||||
china,
|
||||
@@ -35,19 +34,25 @@ enum class country
|
||||
struct age
|
||||
{
|
||||
int m_val;
|
||||
age(int rhs = 0) : m_val(rhs) {}
|
||||
age(int rhs = 0)
|
||||
: m_val(rhs)
|
||||
{}
|
||||
};
|
||||
|
||||
struct name
|
||||
{
|
||||
std::string m_val;
|
||||
name(std::string rhs = "") : m_val(std::move(rhs)) {}
|
||||
name(std::string rhs = "")
|
||||
: m_val(std::move(rhs))
|
||||
{}
|
||||
};
|
||||
|
||||
struct address
|
||||
{
|
||||
std::string m_val;
|
||||
address(std::string rhs = "") : m_val(std::move(rhs)) {}
|
||||
address(std::string rhs = "")
|
||||
: m_val(std::move(rhs))
|
||||
{}
|
||||
};
|
||||
|
||||
struct person
|
||||
@@ -56,7 +61,11 @@ struct person
|
||||
name m_name{};
|
||||
country m_country{};
|
||||
person() = default;
|
||||
person(const age& a, name n, const country& c) : m_age(a), m_name(std::move(n)), m_country(c) {}
|
||||
person(const age& a, name n, const country& c)
|
||||
: m_age(a)
|
||||
, m_name(std::move(n))
|
||||
, m_country(c)
|
||||
{}
|
||||
};
|
||||
|
||||
struct contact
|
||||
@@ -64,7 +73,10 @@ struct contact
|
||||
person m_person{};
|
||||
address m_address{};
|
||||
contact() = default;
|
||||
contact(person p, address a) : m_person(std::move(p)), m_address(std::move(a)) {}
|
||||
contact(person p, address a)
|
||||
: m_person(std::move(p))
|
||||
, m_address(std::move(a))
|
||||
{}
|
||||
};
|
||||
|
||||
struct contact_book
|
||||
@@ -72,27 +84,29 @@ struct contact_book
|
||||
name m_book_name{};
|
||||
std::vector<contact> m_contacts{};
|
||||
contact_book() = default;
|
||||
contact_book(name n, std::vector<contact> c) : m_book_name(std::move(n)), m_contacts(std::move(c)) {}
|
||||
contact_book(name n, std::vector<contact> c)
|
||||
: m_book_name(std::move(n))
|
||||
, m_contacts(std::move(c))
|
||||
{}
|
||||
};
|
||||
} // namespace udt
|
||||
} // namespace udt
|
||||
|
||||
// to_json methods
|
||||
namespace udt
|
||||
{
|
||||
namespace udt {
|
||||
// templates because of the custom_json tests (see below)
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void to_json(BasicJsonType& j, age a)
|
||||
{
|
||||
j = a.m_val;
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void to_json(BasicJsonType& j, const name& n)
|
||||
{
|
||||
j = n.m_val;
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void to_json(BasicJsonType& j, country c)
|
||||
{
|
||||
switch (c)
|
||||
@@ -111,7 +125,7 @@ static void to_json(BasicJsonType& j, country c)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void to_json(BasicJsonType& j, const person& p)
|
||||
{
|
||||
j = BasicJsonType{{"age", p.m_age}, {"name", p.m_name}, {"country", p.m_country}};
|
||||
@@ -164,40 +178,38 @@ static bool operator==(const contact_book& lhs, const contact_book& rhs)
|
||||
return std::tie(lhs.m_book_name, lhs.m_contacts) ==
|
||||
std::tie(rhs.m_book_name, rhs.m_contacts);
|
||||
}
|
||||
} // namespace udt
|
||||
} // namespace udt
|
||||
|
||||
// from_json methods
|
||||
namespace udt
|
||||
{
|
||||
template <typename BasicJsonType>
|
||||
namespace udt {
|
||||
template<typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, age& a)
|
||||
{
|
||||
a.m_val = j.template get<int>();
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, name& n)
|
||||
{
|
||||
n.m_val = j.template get<std::string>();
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, country& c)
|
||||
{
|
||||
const auto str = j.template get<std::string>();
|
||||
const std::map<std::string, country> m =
|
||||
{
|
||||
{"中华人民共和国", country::china},
|
||||
{"France", country::france},
|
||||
{"Российская Федерация", country::russia}
|
||||
};
|
||||
{
|
||||
{"中华人民共和国", country::china},
|
||||
{"France", country::france},
|
||||
{"Российская Федерация", country::russia}};
|
||||
|
||||
const auto it = m.find(str);
|
||||
// TODO(nlohmann) test exceptions
|
||||
c = it->second;
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, person& p)
|
||||
{
|
||||
p.m_age = j["age"].template get<age>();
|
||||
@@ -221,16 +233,13 @@ static void from_json(const nlohmann::json& j, contact_book& cb)
|
||||
cb.m_book_name = j["name"].get<name>();
|
||||
cb.m_contacts = j["contacts"].get<std::vector<contact>>();
|
||||
}
|
||||
} // namespace udt
|
||||
} // namespace udt
|
||||
|
||||
TEST_CASE("basic usage" * doctest::test_suite("udt"))
|
||||
{
|
||||
|
||||
// a bit narcissistic maybe :) ?
|
||||
const udt::age a
|
||||
{
|
||||
23
|
||||
};
|
||||
const udt::age a{
|
||||
23};
|
||||
const udt::name n{"theo"};
|
||||
const udt::country c{udt::country::france};
|
||||
const udt::person sfinae_addict{a, n, c};
|
||||
@@ -252,7 +261,6 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
|
||||
CHECK(
|
||||
json(book) ==
|
||||
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json);
|
||||
|
||||
}
|
||||
|
||||
SECTION("conversion from json via free-functions")
|
||||
@@ -326,19 +334,19 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
|
||||
}
|
||||
}
|
||||
|
||||
namespace udt
|
||||
{
|
||||
namespace udt {
|
||||
struct legacy_type
|
||||
{
|
||||
std::string number{};
|
||||
legacy_type() = default;
|
||||
legacy_type(std::string n) : number(std::move(n)) {}
|
||||
legacy_type(std::string n)
|
||||
: number(std::move(n))
|
||||
{}
|
||||
};
|
||||
} // namespace udt
|
||||
} // namespace udt
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
template <typename T>
|
||||
namespace nlohmann {
|
||||
template<typename T>
|
||||
struct adl_serializer<std::shared_ptr<T>>
|
||||
{
|
||||
static void to_json(json& j, const std::shared_ptr<T>& opt)
|
||||
@@ -361,12 +369,12 @@ struct adl_serializer<std::shared_ptr<T>>
|
||||
}
|
||||
else
|
||||
{
|
||||
opt.reset(new T(j.get<T>())); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
opt.reset(new T(j.get<T>())); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct adl_serializer<udt::legacy_type>
|
||||
{
|
||||
static void to_json(json& j, const udt::legacy_type& l)
|
||||
@@ -379,7 +387,7 @@ struct adl_serializer<udt::legacy_type>
|
||||
l.number = std::to_string(j.get<int>());
|
||||
}
|
||||
};
|
||||
} // namespace nlohmann
|
||||
} // namespace nlohmann
|
||||
|
||||
TEST_CASE("adl_serializer specialization" * doctest::test_suite("udt"))
|
||||
{
|
||||
@@ -392,7 +400,7 @@ TEST_CASE("adl_serializer specialization" * doctest::test_suite("udt"))
|
||||
json j = optPerson;
|
||||
CHECK(j.is_null());
|
||||
|
||||
optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-shared)
|
||||
optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-shared)
|
||||
j = optPerson;
|
||||
CHECK_FALSE(j.is_null());
|
||||
|
||||
@@ -433,9 +441,8 @@ TEST_CASE("adl_serializer specialization" * doctest::test_suite("udt"))
|
||||
}
|
||||
}
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
template <>
|
||||
namespace nlohmann {
|
||||
template<>
|
||||
struct adl_serializer<std::vector<float>>
|
||||
{
|
||||
using type = std::vector<float>;
|
||||
@@ -455,20 +462,19 @@ struct adl_serializer<std::vector<float>>
|
||||
return {4.0, 5.0, 6.0};
|
||||
}
|
||||
};
|
||||
} // namespace nlohmann
|
||||
} // namespace nlohmann
|
||||
|
||||
TEST_CASE("even supported types can be specialized" * doctest::test_suite("udt"))
|
||||
{
|
||||
json const j = std::vector<float> {1.0, 2.0, 3.0};
|
||||
json const j = std::vector<float>{1.0, 2.0, 3.0};
|
||||
CHECK(j.dump() == R"("hijacked!")");
|
||||
auto f = j.get<std::vector<float>>();
|
||||
// the single argument from_json method is preferred
|
||||
CHECK((f == std::vector<float> {4.0, 5.0, 6.0}));
|
||||
CHECK((f == std::vector<float>{4.0, 5.0, 6.0}));
|
||||
}
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
template <typename T>
|
||||
namespace nlohmann {
|
||||
template<typename T>
|
||||
struct adl_serializer<std::unique_ptr<T>>
|
||||
{
|
||||
static void to_json(json& j, const std::unique_ptr<T>& opt)
|
||||
@@ -494,7 +500,7 @@ struct adl_serializer<std::unique_ptr<T>>
|
||||
return std::unique_ptr<T>(new T(j.get<T>()));
|
||||
}
|
||||
};
|
||||
} // namespace nlohmann
|
||||
} // namespace nlohmann
|
||||
|
||||
TEST_CASE("Non-copyable types" * doctest::test_suite("udt"))
|
||||
{
|
||||
@@ -505,7 +511,7 @@ TEST_CASE("Non-copyable types" * doctest::test_suite("udt"))
|
||||
json j = optPerson;
|
||||
CHECK(j.is_null());
|
||||
|
||||
optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-unique)
|
||||
optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-unique)
|
||||
j = optPerson;
|
||||
CHECK_FALSE(j.is_null());
|
||||
|
||||
@@ -530,14 +536,16 @@ TEST_CASE("Non-copyable types" * doctest::test_suite("udt"))
|
||||
// custom serializer - advanced usage
|
||||
// pack structs that are pod-types (but not scalar types)
|
||||
// relies on adl for any other type
|
||||
template <typename T, typename = void>
|
||||
template<typename T, typename = void>
|
||||
struct pod_serializer
|
||||
{
|
||||
// use adl for non-pods, or scalar types
|
||||
template <
|
||||
typename BasicJsonType, typename U = T,
|
||||
typename std::enable_if <
|
||||
!(std::is_pod<U>::value && std::is_class<U>::value), int >::type = 0 >
|
||||
template<
|
||||
typename BasicJsonType,
|
||||
typename U = T,
|
||||
typename std::enable_if<
|
||||
!(std::is_pod<U>::value && std::is_class<U>::value),
|
||||
int>::type = 0>
|
||||
static void from_json(const BasicJsonType& j, U& t)
|
||||
{
|
||||
using nlohmann::from_json;
|
||||
@@ -545,10 +553,8 @@ struct pod_serializer
|
||||
}
|
||||
|
||||
// special behaviour for pods
|
||||
template < typename BasicJsonType, typename U = T,
|
||||
typename std::enable_if <
|
||||
std::is_pod<U>::value && std::is_class<U>::value, int >::type = 0 >
|
||||
static void from_json(const BasicJsonType& j, U& t)
|
||||
template<typename BasicJsonType, typename U = T, typename std::enable_if<std::is_pod<U>::value && std::is_class<U>::value, int>::type = 0>
|
||||
static void from_json(const BasicJsonType& j, U& t)
|
||||
{
|
||||
std::uint64_t value = 0;
|
||||
// The following block is no longer relevant in this serializer, make another one that shows the issue
|
||||
@@ -566,34 +572,33 @@ struct pod_serializer
|
||||
// calling get calls from_json, for now, we cannot do this in custom
|
||||
// serializers
|
||||
nlohmann::from_json(j, value);
|
||||
auto* bytes = static_cast<char*>(static_cast<void*>(&value)); // NOLINT(bugprone-casting-through-void)
|
||||
auto* bytes = static_cast<char*>(static_cast<void*>(&value)); // NOLINT(bugprone-casting-through-void)
|
||||
std::memcpy(&t, bytes, sizeof(value));
|
||||
}
|
||||
|
||||
template <
|
||||
typename BasicJsonType, typename U = T,
|
||||
typename std::enable_if <
|
||||
!(std::is_pod<U>::value && std::is_class<U>::value), int >::type = 0 >
|
||||
static void to_json(BasicJsonType& j, const T& t)
|
||||
template<
|
||||
typename BasicJsonType,
|
||||
typename U = T,
|
||||
typename std::enable_if<
|
||||
!(std::is_pod<U>::value && std::is_class<U>::value),
|
||||
int>::type = 0>
|
||||
static void to_json(BasicJsonType& j, const T& t)
|
||||
{
|
||||
using nlohmann::to_json;
|
||||
to_json(j, t);
|
||||
}
|
||||
|
||||
template < typename BasicJsonType, typename U = T,
|
||||
typename std::enable_if <
|
||||
std::is_pod<U>::value && std::is_class<U>::value, int >::type = 0 >
|
||||
static void to_json(BasicJsonType& j, const T& t) noexcept
|
||||
template<typename BasicJsonType, typename U = T, typename std::enable_if<std::is_pod<U>::value && std::is_class<U>::value, int>::type = 0>
|
||||
static void to_json(BasicJsonType& j, const T& t) noexcept
|
||||
{
|
||||
const auto* bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t)); // NOLINT(bugprone-casting-through-void)
|
||||
const auto* bytes = static_cast<const unsigned char*>(static_cast<const void*>(&t)); // NOLINT(bugprone-casting-through-void)
|
||||
std::uint64_t value = 0;
|
||||
std::memcpy(&value, bytes, sizeof(value));
|
||||
nlohmann::to_json(j, value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace udt
|
||||
{
|
||||
namespace udt {
|
||||
struct small_pod
|
||||
{
|
||||
int begin;
|
||||
@@ -605,16 +610,18 @@ struct non_pod
|
||||
{
|
||||
std::string s{};
|
||||
non_pod() = default;
|
||||
non_pod(std::string S) : s(std::move(S)) {}
|
||||
non_pod(std::string S)
|
||||
: s(std::move(S))
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void to_json(BasicJsonType& j, const non_pod& np)
|
||||
{
|
||||
j = np.s;
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, non_pod& np)
|
||||
{
|
||||
np.s = j.template get<std::string>();
|
||||
@@ -626,7 +633,7 @@ static bool operator==(small_pod lhs, small_pod rhs) noexcept
|
||||
std::tie(rhs.begin, rhs.middle, rhs.end);
|
||||
}
|
||||
|
||||
static bool operator==(const non_pod& lhs, const non_pod& rhs) noexcept
|
||||
static bool operator==(const non_pod& lhs, const non_pod& rhs) noexcept
|
||||
{
|
||||
return lhs.s == rhs.s;
|
||||
}
|
||||
@@ -635,13 +642,12 @@ static std::ostream& operator<<(std::ostream& os, small_pod l)
|
||||
{
|
||||
return os << "begin: " << l.begin << ", middle: " << l.middle << ", end: " << l.end;
|
||||
}
|
||||
} // namespace udt
|
||||
} // namespace udt
|
||||
|
||||
TEST_CASE("custom serializer for pods" * doctest::test_suite("udt"))
|
||||
{
|
||||
using custom_json =
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||
std::int64_t, std::uint64_t, double, std::allocator, pod_serializer>;
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator, pod_serializer>;
|
||||
|
||||
auto p = udt::small_pod{42, '/', 42};
|
||||
custom_json const j = p;
|
||||
@@ -656,12 +662,12 @@ TEST_CASE("custom serializer for pods" * doctest::test_suite("udt"))
|
||||
CHECK(np == np2);
|
||||
}
|
||||
|
||||
template <typename T, typename>
|
||||
template<typename T, typename>
|
||||
struct another_adl_serializer;
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator, another_adl_serializer>;
|
||||
|
||||
template <typename T, typename>
|
||||
template<typename T, typename>
|
||||
struct another_adl_serializer
|
||||
{
|
||||
static void from_json(const custom_json& j, T& t)
|
||||
@@ -718,7 +724,7 @@ TEST_CASE("different basic_json types conversions")
|
||||
{
|
||||
json const j = {1, 2, 3};
|
||||
custom_json const cj = j;
|
||||
CHECK((cj == std::vector<int> {1, 2, 3}));
|
||||
CHECK((cj == std::vector<int>{1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("integer")
|
||||
@@ -775,42 +781,43 @@ TEST_CASE("different basic_json types conversions")
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
struct incomplete;
|
||||
|
||||
// std::is_constructible is broken on macOS' libc++
|
||||
// use the cppreference implementation
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct is_constructible_patched : std::false_type {};
|
||||
template<typename T, typename = void>
|
||||
struct is_constructible_patched : std::false_type
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct is_constructible_patched<T, decltype(void(json(std::declval<T>())))> : std::true_type {};
|
||||
} // namespace
|
||||
template<typename T>
|
||||
struct is_constructible_patched<T, decltype(void(json(std::declval<T>())))> : std::true_type
|
||||
{};
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated context" * doctest::test_suite("udt"))
|
||||
{
|
||||
static_assert(!is_constructible_patched<json, incomplete>::value, "");
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
class Evil
|
||||
{
|
||||
public:
|
||||
Evil() = default;
|
||||
template <typename T>
|
||||
Evil(T t) : m_i(sizeof(t))
|
||||
template<typename T>
|
||||
Evil(T t)
|
||||
: m_i(sizeof(t))
|
||||
{
|
||||
static_cast<void>(t); // fix MSVC's C4100 warning
|
||||
static_cast<void>(t); // fix MSVC's C4100 warning
|
||||
}
|
||||
|
||||
int m_i = 0;
|
||||
};
|
||||
|
||||
void from_json(const json& /*unused*/, Evil& /*unused*/) {}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Issue #924")
|
||||
{
|
||||
@@ -827,17 +834,17 @@ TEST_CASE("Issue #924")
|
||||
|
||||
TEST_CASE("Issue #1237")
|
||||
{
|
||||
struct non_convertible_type {};
|
||||
struct non_convertible_type
|
||||
{};
|
||||
static_assert(!std::is_convertible<json, non_convertible_type>::value, "");
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
class no_iterator_type
|
||||
{
|
||||
public:
|
||||
no_iterator_type(std::initializer_list<int> l)
|
||||
: _v(l)
|
||||
: _v(l)
|
||||
{}
|
||||
|
||||
std::vector<int>::const_iterator begin() const
|
||||
|
||||
Reference in New Issue
Block a user