Skip to content

Commit

Permalink
add first version support for user-defined types
Browse files Browse the repository at this point in the history
  • Loading branch information
Théo Delrieu committed Oct 17, 2016
1 parent 67b9f19 commit a2a8fec
Show file tree
Hide file tree
Showing 3 changed files with 363 additions and 19 deletions.
81 changes: 62 additions & 19 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ SOFTWARE.
*/
namespace nlohmann
{

template <typename T, typename = void>
struct json_traits;

/*!
@brief unnamed namespace with internal helper functions
@since version 1.0.0
*/
// TODO transform this anon ns to detail?
namespace
{
/*!
Expand All @@ -122,6 +124,27 @@ struct has_mapped_type
std::is_integral<decltype(detect(std::declval<T>()))>::value;
};

// taken from http://stackoverflow.com/questions/10711952/how-to-detect-existence-of-a-class-using-sfinae
template <typename T>
struct has_destructor
{
template <typename U>
static std::true_type detect(decltype(std::declval<U>().~U())*);

template <typename>
static std::false_type detect(...);

static constexpr bool value = decltype(detect<T>(0))::value;
};

template<typename T>
struct has_json_traits
{
static constexpr bool value = has_destructor<json_traits<T>>::value;
};

template <> struct has_json_traits<void> : std::false_type {};

/*!
@brief helper class to create locales with decimal point
Expand Down Expand Up @@ -1225,6 +1248,15 @@ class basic_json
assert_invariant();
}

template <
typename T,
typename =
typename std::enable_if<has_json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::value>::type>
explicit basic_json(T &&val)
: basic_json(json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::
to_json(std::forward<T>(val))) {}
/*!
@brief create a string (explicit)
Expand All @@ -1241,15 +1273,14 @@ class basic_json
@sa @ref basic_json(const typename string_t::value_type*) -- create a
string value from a character pointer
@sa @ref basic_json(const CompatibleStringType&) -- create a string value
@sa @ref basic_json(const CompatibleStringType&) -- create a string
value
from a compatible string container
@since version 1.0.0
*/
basic_json(const string_t& val)
: m_type(value_t::string), m_value(val)
{
assert_invariant();
basic_json(const string_t &val) : m_type(value_t::string), m_value(val) {
assert_invariant();
}

/*!
Expand Down Expand Up @@ -2584,20 +2615,32 @@ class basic_json
// value access //
//////////////////

template <
typename T,
typename =
typename std::enable_if<has_json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::value>::type>
auto get_impl(T *) const -> decltype(
json_traits<typename std::remove_cv<typename std::remove_reference<
T>::type>::type>::from_json(std::declval<basic_json>())) {
return json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::from_json(*this);
}

/// get an object (explicit)
template<class T, typename std::enable_if<
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
T get_impl(T*) const
{
if (is_object())
{
return T(m_value.object->begin(), m_value.object->end());
}
else
{
throw std::domain_error("type must be object, but is " + type_name());
}
template <class T,
typename std::enable_if<
std::is_convertible<typename object_t::key_type,
typename T::key_type>::value and
std::is_convertible<basic_json_t,
typename T::mapped_type>::value,
int>::type = 0>
T get_impl(T *) const {
if (is_object()) {
return T(m_value.object->begin(), m_value.object->end());
} else {
throw std::domain_error("type must be object, but is " + type_name());
}
}

/// get an object (explicit)
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ add_executable(${JSON_UNITTEST_TARGET_NAME}
"src/unit-concepts.cpp"
"src/unit-constructor1.cpp"
"src/unit-constructor2.cpp"
"src/unit-constructor3.cpp"
"src/unit-convenience.cpp"
"src/unit-conversions.cpp"
"src/unit-deserialization.cpp"
Expand Down
Loading

0 comments on commit a2a8fec

Please sign in to comment.