16#include <jsonv/serialization/container_adapter.hpp>
553class formats_builder;
555template <
typename T>
class adapter_builder;
556template <
typename T,
typename TMember>
class member_adapter_builder;
557template <
typename TPo
inter>
class polymorphic_adapter_builder;
562class formats_builder_dsl
565 explicit formats_builder_dsl(formats_builder* owner) :
569 template <
typename T>
570 adapter_builder<T> type();
572 template <
typename T,
typename F>
573 adapter_builder<T> type(F&&);
575 template <
typename TEnum>
576 formats_builder& enum_type(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
578 template <
typename TEnum>
579 formats_builder& enum_type_icase(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
581 template <
typename TPo
inter>
582 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key =
"");
584 template <
typename TPo
inter,
typename F>
585 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key, F&&);
587 template <
typename F>
588 formats_builder& extend(F&&);
590 formats_builder& register_adapter(
const adapter* p);
591 formats_builder& register_adapter(std::shared_ptr<const adapter> p);
593 formats_builder& reference_type(std::type_index typ);
594 formats_builder& reference_type(std::type_index type, std::type_index from);
596 template <
typename TOptional>
597 formats_builder& register_optional();
599 template <
typename TContainer>
600 formats_builder& register_container();
602 template <
typename T,
template <
class...>
class... TTContainers>
603 formats_builder& register_containers();
605 template <
typename TWrapper>
606 formats_builder& register_wrapper();
608 formats_builder& check_references(
const formats& other,
const std::string& name =
"");
609 formats_builder& check_references(
const formats::list& others,
const std::string& name =
"");
610 formats_builder& check_references(
const std::string& name =
"");
614 formats compose_checked(formats other,
const std::string& name =
"");
615 formats compose_checked(std::vector<formats> others,
const std::string& name =
"");
617 operator formats()
const;
620 formats_builder* owner;
624class adapter_builder_dsl
627 explicit adapter_builder_dsl(adapter_builder<T>* owner) :
631 adapter_builder<T>& type_default_on_null(
bool on =
true);
633 adapter_builder<T>& type_default_value(std::function<T (
const extraction_context& ctx)> create);
635 adapter_builder<T>& type_default_value(
const T& value);
637 template <
typename TMember>
638 member_adapter_builder<T, TMember> member(std::string name, TMember T::*selector);
640 template <
typename TMember>
641 member_adapter_builder<T, TMember> member(std::string name,
642 std::function<
const TMember& (
const T&)> access,
643 std::function<
void (T&, TMember&&)> mutate
646 template <
typename TMember>
647 member_adapter_builder<T, TMember> member(std::string name,
648 const TMember& (T::*access)() const,
649 TMember& (T::*mutable_access)()
652 template <
typename TMember>
653 member_adapter_builder<T, TMember> member(std::string name,
654 const TMember& (T::*access)() const,
655 void (T::*mutate)(TMember)
658 template <
typename TMember>
659 member_adapter_builder<T, TMember> member(std::string name,
660 const TMember& (T::*access)() const,
661 void (T::*mutate)(TMember&&)
664 adapter_builder<T>& pre_extract(
typename adapter_builder<T>::pre_extract_func perform);
666 adapter_builder<T>& post_extract(
typename adapter_builder<T>::post_extract_func perform);
668 adapter_builder<T>& on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler);
671 adapter_builder<T>* owner;
678 virtual ~member_adapter() noexcept
681 virtual void mutate(
const extraction_context& context,
const value& from, T& out)
const = 0;
683 virtual void to_json(
const serialization_context& context,
const T& from, value& out)
const = 0;
685 virtual bool has_extract_key(std::string_view key)
const = 0;
688template <
typename T,
typename TMember>
689class member_adapter_impl :
690 public member_adapter<T>
693 using mutator_type = std::function<void (T&, TMember&&)>;
694 using accessor_type = std::function<
const TMember& (
const T&)>;
697 explicit member_adapter_impl(std::string name, mutator_type mutator, accessor_type access) :
698 _names({ std::move(name) }),
699 _set_value(std::move(mutator)),
700 _get_value(std::move(access))
703 explicit member_adapter_impl(std::string name, TMember T::*selector) :
704 member_adapter_impl(
std::move(name),
705 [selector] (T& value, TMember&& x) { value.*selector = std::move(x); },
706 [selector] (
const T& value) ->
const TMember& {
return value.*selector; }
710 virtual void mutate(
const extraction_context& context,
const value& from, T& out)
const override
712 value::const_object_iterator iter;
713 for (
const auto& name : _names)
714 if ((iter = from.find(name)) != from.end_object())
717 bool use_default =
false;
718 if (iter == from.end_object())
720 use_default = bool(_default_value);
722 throw extraction_error(context.path(), std::string(
"Missing required field ") + _names.at(0));
724 else if (_default_on_null && iter->second.kind() == kind::null)
730 _set_value(out, _default_value(context, from));
732 _set_value(out, context.extract_sub<TMember>(from, iter->first));
735 virtual void to_json(
const serialization_context& context,
const T& from, value& out)
const override
737 if (should_encode(context, from))
738 out.
insert({ _names.at(0), context.to_json(_get_value(from)) });
741 virtual bool has_extract_key(std::string_view key)
const override
743 return std::any_of(begin(_names), end(_names), [key] (
const std::string& name) {
return name == key; });
746 void add_encode_check(std::function<
bool (
const serialization_context&,
const TMember&)>
check)
750 auto old_check = std::move(_should_encode);
751 _should_encode = [
check, old_check] (
const serialization_context& context,
const TMember& value)
753 return check(context, value) && old_check(context, value);
758 _should_encode = std::move(
check);
762 void add_extraction_mutator(std::function <TMember (TMember&&)> mutate)
766 auto old_mutate = std::move(_extract_mutate);
767 _extract_mutate = [old_mutate, mutate] (TMember&& member) {
return mutate(old_mutate(std::move(member))); };
771 _extract_mutate = std::move(mutate);
775 void add_extraction_check(std::function <
void (
const TMember&)>
check)
777 add_extraction_mutator([
check] (TMember&& value)
784 void default_value(std::function<TMember (
const extraction_context&,
const value&)>&& create)
786 _default_value = std::move(create);
789 void default_on_null(
bool on)
791 _default_on_null = on;
795 bool should_encode(
const serialization_context& context,
const T& from)
const
798 return _should_encode(context, _get_value(from));
804 template <
typename U,
typename UMember>
805 friend class member_adapter_builder;
808 std::vector<std::string> _names;
809 mutator_type _set_value;
810 accessor_type _get_value;
811 std::function<bool (
const serialization_context&,
const TMember&)> _should_encode;
812 std::function<TMember (
const extraction_context&,
const value&)> _default_value;
813 bool _default_on_null =
false;
814 std::function<TMember (TMember&&)> _extract_mutate;
819template <
typename T,
typename TMember>
821 public detail::formats_builder_dsl,
822 public detail::adapter_builder_dsl<T>
827 detail::member_adapter_impl<T, TMember>*
adapter
833 reference_type(std::type_index(
typeid(
TMember)), std::type_index(
typeid(T)));
839 _adapter->_names.emplace_back(std::move(
name));
845 _adapter->add_extraction_check(std::move(
check));
849 member_adapter_builder& check_input(std::function<
bool (
const TMember&)>
check,
850 std::function<
void (
const TMember&)> thrower
853 _adapter->add_extraction_check([
check, thrower] (
const TMember& value)
861 template <
typename TException>
862 member_adapter_builder& check_input(std::function<
void (
const TMember&)>
check,
const TException& ex)
864 return check_input(std::move(
check), [ex] (
const TMember&) {
throw ex; });
872 _adapter->default_value(std::move(create));
887 _adapter->default_on_null(
on);
896 _adapter->add_encode_check(std::move(
check));
941 detail::member_adapter_impl<T, TMember>* _adapter;
946 public detail::formats_builder_dsl
954 template <
typename F>
956 formats_builder_dsl(owner),
959 auto adapter = std::make_shared<adapter_impl>();
963 std::forward<F>(
f)(*this);
972 _adapter->_default_on_null =
on;
978 _adapter->_create_default = std::move(create);
987 template <
typename TMember>
990 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
992 new detail::member_adapter_impl<T, TMember>(std::move(
name),
selector)
995 _adapter->_members.emplace_back(std::move(ptr));
999 template <
typename TMember>
1002 std::function<
void (T&,
TMember&&)> mutate
1005 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
1007 new detail::member_adapter_impl<T, TMember>(std::move(
name), std::move(mutate), std::move(
access))
1010 _adapter->_members.emplace_back(std::move(ptr));
1014 template <
typename TMember>
1026 template <
typename TMember>
1038 template <
typename TMember>
1046 std::function<
void (T&,
TMember&&)>(mutate)
1052 if (_adapter->_pre_extract)
1054 pre_extract_func
old_perform = std::move(_adapter->_pre_extract);
1063 _adapter->_pre_extract = std::move(
perform);
1070 if (_adapter->_post_extract)
1072 post_extract_func
old_perform = std::move(_adapter->_post_extract);
1080 _adapter->_post_extract = std::move(
perform);
1087 adapter_impl*
adapter = _adapter;
1092 return std::any_of(begin(
adapter->_members), end(
adapter->_members),
1093 [key] (
const std::unique_ptr<detail::member_adapter<T>>&
mem)
1095 return mem->has_extract_key(key);
1100 for (
const auto&
pair :
from.as_object())
1109 class adapter_impl :
1114 _default_on_null(
false)
1122 if (_default_on_null &&
from.is_null())
1123 return _create_default(
context);
1126 for (
const auto& member : _members)
1138 for (
const auto& member : _members)
1143 std::deque<std::unique_ptr<detail::member_adapter<T>>> _members;
1144 pre_extract_func _pre_extract;
1145 post_extract_func _post_extract;
1147 bool _default_on_null;
1151 adapter_impl* _adapter;
1154template <
typename TPo
inter>
1156 public detail::formats_builder_dsl
1159 template <
typename F>
1164 formats_builder_dsl(owner),
1168 auto adapter = std::make_shared<polymorphic_adapter<TPointer>>();
1172 std::forward<F>(
f)(*this);
1184 _adapter->check_null_input(
on);
1190 _adapter->check_null_output(
on);
1194 template <
typename TSub>
1198 if (_discrimination_key.empty())
1199 throw std::logic_error(
"Cannot use single-argument subtype if no discrimination_key has been set");
1204 template <
typename TSub>
1212 reference_type(std::type_index(
typeid(
TSub)), std::type_index(
typeid(
TPointer)));
1216 template <
typename TSub>
1220 reference_type(std::type_index(
typeid(
TSub)), std::type_index(
typeid(
TPointer)));
1224 template <
typename TSub>
1236 std::string _discrimination_key;
1244 template <
typename T>
1250 template <
typename T,
typename F>
1256 template <
typename TEnum>
1258 std::initializer_list<std::pair<TEnum, value>>
mapping
1264 template <
typename TEnum>
1266 std::initializer_list<std::pair<TEnum, value>>
mapping
1272 template <
typename TPo
inter>
1279 template <
typename TPo
inter,
typename F>
1286 template <
typename F>
1289 std::forward<F>(
func)(*this);
1295 _formats.register_adapter(
p, _duplicate_type_action);
1301 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1305 template <
typename TOptional>
1308 reference_type(std::type_index(
typeid(
typename TOptional::value_type)), std::type_index(
typeid(
TOptional)));
1310 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1314 template <
typename TContainer>
1317 reference_type(std::type_index(
typeid(
typename TContainer::value_type)), std::type_index(
typeid(
TContainer)));
1319 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1323 template <
typename TWrapper>
1326 reference_type(std::type_index(
typeid(
typename TWrapper::value_type)), std::type_index(
typeid(
TWrapper)));
1328 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1332 template <
typename T>
1338 template <
typename T,
template <
class...>
class TTContainer,
template <
class...>
class...
TTRest>
1342 return register_containers<T,
TTRest...>();
1372 formats compose_checked(
const formats::list&
others,
const std::string&
name =
"");
1386 std::map<std::type_index, std::set<std::type_index>> _referenced_types;
1392template <
typename T>
1395 return owner->type<T>();
1398template <
typename T,
typename F>
1399adapter_builder<T> formats_builder_dsl::type(F&& f)
1401 return owner->type<T>(std::forward<F>(f));
1404template <
typename TEnum>
1405formats_builder& formats_builder_dsl::enum_type(std::string enum_name,
1406 std::initializer_list<std::pair<TEnum, value>> mapping
1409 return owner->enum_type<TEnum>(std::move(enum_name), mapping);
1412template <
typename TEnum>
1413formats_builder& formats_builder_dsl::enum_type_icase(std::string enum_name,
1414 std::initializer_list<std::pair<TEnum, value>> mapping
1417 return owner->enum_type_icase<TEnum>(std::move(enum_name), mapping);
1420template <
typename TPo
inter>
1421polymorphic_adapter_builder<TPointer>
1422formats_builder_dsl::polymorphic_type(std::string discrimination_key)
1424 return owner->polymorphic_type<TPointer>(std::move(discrimination_key));
1427template <
typename TPo
inter,
typename F>
1428polymorphic_adapter_builder<TPointer>
1429formats_builder_dsl::polymorphic_type(std::string discrimination_key, F&& f)
1431 return owner->polymorphic_type<TPointer>(std::move(discrimination_key), std::forward<F>(f));
1434template <
typename F>
1435formats_builder& formats_builder_dsl::extend(F&& f)
1437 return owner->extend(std::forward<F>(f));
1440template <
typename TOptional>
1441formats_builder& formats_builder_dsl::register_optional()
1443 return owner->register_optional<TOptional>();
1446template <
typename TContainer>
1447formats_builder& formats_builder_dsl::register_container()
1449 return owner->register_container<TContainer>();
1452template <
typename T,
template <
class...>
class... TTContainers>
1453formats_builder& formats_builder_dsl::register_containers()
1455 return owner->register_containers<T, TTContainers...>();
1458template <
typename TWrapper>
1459formats_builder& formats_builder_dsl::register_wrapper()
1461 return owner->register_container<TWrapper>();
1464template <
typename T>
1465adapter_builder<T>& adapter_builder_dsl<T>::type_default_on_null(
bool on)
1467 return owner->type_default_on_null(on);
1470template <
typename T>
1471adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(std::function<T (
const extraction_context& ctx)> create)
1473 return owner->type_default_value(std::move(create));
1476template <
typename T>
1477adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(
const T& value)
1479 return owner->type_default_value(value);
1482template <
typename T>
1483template <
typename TMember>
1484member_adapter_builder<T, TMember> adapter_builder_dsl<T>::member(std::string name, TMember T::*selector)
1486 return owner->member(std::move(name), selector);
1489template <
typename T>
1490template <
typename TMember>
1491member_adapter_builder<T, TMember>
1492adapter_builder_dsl<T>::member(std::string name,
1493 std::function<
const TMember& (
const T&)> access,
1494 std::function<
void (T&, TMember&&)> mutate
1497 return owner->member(std::move(name), std::move(access), std::move(mutate));
1500template <
typename T>
1501template <
typename TMember>
1502member_adapter_builder<T, TMember>
1503adapter_builder_dsl<T>::member(std::string name,
1504 const TMember& (T::*access)() const,
1505 TMember& (T::*mutable_access)()
1508 return owner->member(std::move(name), access, mutable_access);
1511template <
typename T>
1512template <
typename TMember>
1513member_adapter_builder<T, TMember>
1514adapter_builder_dsl<T>::member(std::string name,
1515 const TMember& (T::*access)() const,
1516 void (T::*mutate)(TMember)
1519 return owner->member(std::move(name), access, mutate);
1522template <
typename T>
1523template <
typename TMember>
1524member_adapter_builder<T, TMember>
1525adapter_builder_dsl<T>::member(std::string name,
1526 const TMember& (T::*access)() const,
1527 void (T::*mutate)(TMember&&)
1530 return owner->member(std::move(name), access, mutate);
1533template <
typename T>
1534adapter_builder<T>& adapter_builder_dsl<T>::pre_extract(
typename adapter_builder<T>::pre_extract_func perform)
1536 return owner->pre_extract(std::move(perform));
1539template <
typename T>
1540adapter_builder<T>& adapter_builder_dsl<T>::post_extract(
typename adapter_builder<T>::post_extract_func perform)
1542 return owner->post_extract(std::move(perform));
1545template <
typename T>
1546adapter_builder<T>& adapter_builder_dsl<T>::on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler)
1548 return owner->on_extract_extra_keys(std::move(handler));
An adapter for the type T.
An adapter is both an extractor and a serializer.
An adapter for enumeration types.
member_adapter_builder & default_value(TMember value)
If the key for this member is not in the object when deserializing, use this value.
member_adapter_builder & encode_if(std::function< bool(const serialization_context &, const TMember &)> check)
Only encode this member if the check passes.
member_adapter_builder & since(version ver)
Only encode this member if the serialization_context::version is greater than or equal to ver.
member_adapter_builder & alternate_name(std::string name)
When extracting, also look for this name as a key.
member_adapter_builder & default_on_null(bool on=true)
Should a kind::null for a key be interpreted as a missing value?
member_adapter_builder & after(version ver)
Only encode this member if the serialization_context::version is greater than ver.
member_adapter_builder & before(version ver)
Only encode this member if the serialization_context::version is less than ver.
member_adapter_builder & default_value(std::function< TMember(const extraction_context &, const value &)> create)
If the key for this member is not in the object when deserializing, call this function to create a va...
member_adapter_builder & until(version ver)
Only encode this member if the serialization_context::version is less than or equal to ver.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
array_iterator insert(const_array_iterator position, value item)
Insert an item into position on this array.
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_NO_RETURN
Mark that a given function will never return control to the caller, either by exiting or throwing an ...
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Copyright (c) 2015 by Travis Gockel.
Copyright (c) 2015-2020 by Travis Gockel.
duplicate_type_action
The action to take when an insertion of an extractor or serializer into a formats is attempted,...
value to_json(const T &from, const formats &fmts)
Encode a JSON value from from using the provided fmts.
keyed_subtype_action
What to do when serializing a keyed subtype of a polymorphic_adapter.
@ check
Ensure the correct key/value pair was inserted by serialization. Throws std::runtime_error if it wasn...
@ none
Don't do any checking or insertion of the expected key/value pair.
JSONV_PUBLIC value object()
Create an empty object.
Copyright (c) 2015-2020 by Travis Gockel.
Copyright (c) 2017-2020 by Travis Gockel.
Conversion between C++ types and JSON values.
JSONV_NO_RETURN JSONV_PUBLIC void throw_extra_keys_extraction_error(const extraction_context &context, const value &from, const std::set< std::string > &extra_keys)
Throw an extraction_error indicating that from had extra keys.
Represents a version used to extract and encode JSON objects from C++ classes.
Copyright (c) 2015-2020 by Travis Gockel.