13 #ifndef __JSONV_SERIALIZATION_UTIL_HPP_INCLUDED__ 14 #define __JSONV_SERIALIZATION_UTIL_HPP_INCLUDED__ 21 #include <initializer_list> 24 #include <type_traits> 38 virtual const std::type_info&
get_type()
const override 48 return extract_impl<T>(context, from, into);
57 -> decltype(U(from, context),
void())
59 new(into) U(from, context);
62 template <
typename U,
typename =
void>
67 -> decltype(U(from),
void())
78 virtual const std::type_info&
get_type()
const override 88 new(into) T(create(context, from));
95 template <
typename T,
typename FExtract>
100 template <
typename FUExtract>
102 _func(std::forward<FUExtract>(func))
108 return create_impl(_func, context, from);
112 template <
typename FUExtract>
114 -> decltype(func(context, from))
116 return func(context, from);
119 template <
typename FUExtract,
typename =
void>
121 -> decltype(func(from))
130 template <
typename FExtract>
131 auto make_extractor(FExtract func)
142 template <
typename FExtract,
typename =
void>
143 auto make_extractor(FExtract func)
152 template <
typename T>
157 virtual const std::type_info&
get_type()
const override 166 return to_json(context, *static_cast<const T*>(from));
175 template <
typename T,
typename FToJson>
180 template <
typename FUToJson>
182 _to_json(std::forward<FUToJson>(to_json_))
189 return to_json_impl(_to_json, context, from);
193 template <
typename FUToJson>
195 -> decltype(func(context, from))
197 return func(context, from);
200 template <
typename FUToJson,
typename =
void>
202 -> decltype(func(from))
211 template <
typename T,
typename FToJson>
217 template <
typename T>
222 virtual const std::type_info&
get_type()
const override 232 new(into) T(create(context, from));
239 return to_json(context, *static_cast<const T*>(from));
248 template <
typename T,
typename FExtract,
typename FToJson>
253 template <
typename FUExtract,
typename FUToJson>
255 _extract(std::forward<FUExtract>(extract_)),
256 _to_json(std::forward<FUToJson>(to_json_))
262 return create_impl(_extract, context, from);
267 return to_json_impl(_to_json, context, from);
271 template <
typename FUExtract>
273 -> decltype(func(context, from))
275 return func(context, from);
278 template <
typename FUExtract,
typename =
void>
280 -> decltype(func(from))
285 template <
typename FUToJson>
287 -> decltype(func(context, from))
289 return func(context, from);
292 template <
typename FUToJson,
typename =
void>
294 -> decltype(func(from))
304 template <
typename FExtract,
typename FToJson>
305 auto make_adapter(FExtract
extract, FToJson to_json_)
315 (std::move(extract), std::move(to_json_));
318 template <
typename FExtract,
typename FToJson,
typename =
void>
319 auto make_adapter(FExtract extract, FToJson to_json_)
329 (std::move(extract), std::move(to_json_));
341 template <
typename TOptional>
345 using element_type =
typename TOptional::value_type;
353 return TOptional(context.
extract<element_type>(from));
371 template <
typename TContainer>
375 using element_type =
typename TContainer::value_type;
384 for (value::size_type idx = 0U; idx < from.
size(); ++idx)
385 out.insert(end(out), context.
extract_sub<element_type>(from, idx));
392 for (
const element_type& x : from)
403 template <
typename TWrapper>
407 using element_type =
typename TWrapper::value_type;
412 return TWrapper(context.
extract<element_type>(from));
417 return context.
to_json(element_type(from));
433 template <
typename TEnum,
434 typename FEnumComp = std::less<TEnum>,
435 typename FValueComp = std::less<value>
445 template <
typename TForwardIterator>
446 explicit enum_adapter(std::string enum_name, TForwardIterator first, TForwardIterator last) :
447 _enum_name(
std::move(enum_name))
449 for (
auto iter = first; iter != last; ++iter)
451 _val_to_cpp.insert({ iter->second, iter->first });
452 _cpp_to_val.insert(*iter);
479 explicit enum_adapter(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping) :
480 enum_adapter(std::move(enum_name), mapping.begin(), mapping.end())
488 auto iter = _val_to_cpp.find(from);
489 if (iter != end(_val_to_cpp))
493 std::string(
"Invalid value for ") + _enum_name +
": " +
to_string(from)
501 auto iter = _cpp_to_val.
find(from);
502 if (iter != end(_cpp_to_val))
509 std::string _enum_name;
510 std::map<value, TEnum, FValueComp> _val_to_cpp;
511 std::map<TEnum, value, FEnumComp> _cpp_to_val;
518 template <
typename TEnum,
typename FEnumComp = std::less<TEnum>>
558 template <
typename TPo
inter>
563 using match_predicate = std::function<bool (const extraction_context&, const value&)>;
573 template <
typename T>
576 _subtype_ctors.emplace_back(std::move(pred),
579 return TPointer(
new T(context.
extract<T>(value)));
589 template <
typename T>
591 value expected_value,
594 std::type_index tidx = std::type_index(
typeid(T));
595 if (!_serialization_actions.emplace(tidx, std::make_tuple(key, expected_value, action)).second)
604 && iter->second == expected_value;
606 return add_subtype<T>(op);
614 _check_null_input = on;
617 bool check_null_input()
const 619 return _check_null_input;
625 _check_null_output = on;
628 bool check_null_output()
const 630 return _check_null_output;
639 if (_check_null_input && from.
is_null())
642 auto iter = std::find_if(begin(_subtype_ctors), end(_subtype_ctors),
643 [&] (
const std::pair<match_predicate, create_function>& pair)
645 return pair.first(context, from);
648 if (iter != end(_subtype_ctors))
649 return iter->second(context, from);
652 std::string(
"No discriminators matched JSON value: ") +
to_string(from)
658 if (_check_null_output && !from)
661 value serialized = context.
to_json(
typeid(*from), static_cast<const void*>(&*from));
663 auto action_iter = _serialization_actions.
find(std::type_index(
typeid(*from)));
664 if (action_iter != _serialization_actions.end())
668 return " polymorphic_adapter<" +
demangle(
typeid(TPointer).name()) +
">" 669 "subtype(" +
demangle(
typeid(*from).name()) +
")";
672 const std::string& key = std::get<0>(action_iter->second);
673 const value& val = std::get<1>(action_iter->second);
682 throw std::runtime_error(
"Expected keyed subtype to serialize as an object." + errmsg());
683 if (!serialized.
count(key))
684 throw std::runtime_error(
"Expected subtype key not found." + errmsg());
685 if (serialized.
at(key) != val)
686 throw std::runtime_error(
"Expected subtype key is not the expected value." + errmsg());
690 throw std::runtime_error(
"Expected keyed subtype to serialize as an object." + errmsg());
691 if (serialized.
count(key))
692 throw std::runtime_error(
"Subtype key already present when trying to insert." + errmsg());
693 serialized[key] = val;
696 throw std::runtime_error(
"Unknown keyed_subtype_action.");
704 using create_function = std::function<TPointer (const extraction_context&, const value&)>;
707 using serialization_action = std::tuple<std::string, value, keyed_subtype_action>;
709 std::vector<std::pair<match_predicate, create_function>> _subtype_ctors;
710 std::map<std::type_index, serialization_action> _serialization_actions;
711 bool _check_null_input =
false;
712 bool _check_null_output =
false;
void add_subtype(match_predicate pred)
Add a subtype which can be transformed into TPointer which will be called if the discriminator pred i...
An adapter for container types.
object_iterator end_object()
Get an iterator to the one past the end of this object.
virtual const std::type_info & get_type() const override
Get the run-time type this extractor knows how to extract.
Don't do any checking or insertion of the expected key/value pair.
void add_subtype_keyed(std::string key, value expected_value, keyed_subtype_action action=keyed_subtype_action::none)
Add a subtype which can be transformed into TPointer which will be called if given a JSON value with ...
Copyright (c) 2015 by Travis Gockel.
bool is_null() const
Tests if this kind is kind::null.
Copyright (c) 2014-2019 by Travis Gockel.
value & at(size_type idx)
Get the value in this array at the given idx.
An adapter is both an extractor and a serializer.
An adapter for optional-like types.
An adapter which can create polymorphic types.
A serializer holds the method for converting an arbitrary C++ type into a value.
object_iterator find(const std::string &key)
Attempt to locate a key-value pair with the provided key in this object.
bool is_object() const
Tests if this kind is kind::object.
JSONV_PUBLIC const value null
An instance with kind::null.
void check_null_output(bool on)
When converting with to_json, should a null input translate into a kind::null?
JSONV_PUBLIC std::string demangle(string_view source)
Convert the input source from a mangled type into a human-friendly version.
size_type count(const std::string &key) const
Check if the given key exists in this object.
keyed_subtype_action
What to do when serializing a keyed subtype of a polymorphic_adapter.
An adapter for enumeration types.
array_view as_array()&
View this instance as an array.
JSONV_PUBLIC value array()
Create an empty array value.
Conversion between C++ types and JSON values.
JSONV_PUBLIC std::string to_string(const parse_error::problem &p)
Get a string representation of a problem.
Insert the correct key/value pair as part of serialization.
virtual value to_json(const serialization_context &context, const void *from) const override
Create a value from the value in the given region of memory.
An adapter for "wrapper" types.
Exception thrown if an insertion of an extractor or serializer into a formats is attempted, but there is already an extractor or serializer for that type.
virtual const std::type_info & get_type() const override
Get the run-time type this serialize knows how to encode.
Ensure the correct key/value pair was inserted by serialization.
value to_json(const T &from, const formats &fmts)
Encode a JSON value from from using the provided fmts.
virtual void extract(const extraction_context &context, const value &from, void *into) const override
Extract a the type from a value into a region of memory.
enum_adapter(std::string enum_name, TForwardIterator first, TForwardIterator last)
Create an adapter with mapping values from the range [first, last).
value to_json(const T &from) const
Convenience function for converting a C++ object into a JSON value.
virtual value to_json(const serialization_context &context, const void *from) const override
Create a value from the value in the given region of memory.
void check_null_input(bool on)
When extracting a C++ value, should kind::null in JSON automatically become a default-constructed TPo...
size_type size() const
Get the number of items in this value.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
void push_back(value item)
Push item to the back of this array.
A collection of function objects a la <functional>.