12 #ifndef __JSONV_SERIALIZATION_BUILDER_HPP_INCLUDED__ 13 #define __JSONV_SERIALIZATION_BUILDER_HPP_INCLUDED__ 23 #include <type_traits> 554 class formats_builder;
556 template <
typename T>
class adapter_builder;
557 template <
typename T,
typename TMember>
class member_adapter_builder;
558 template <
typename TPo
inter>
class polymorphic_adapter_builder;
570 template <
typename T>
573 template <
typename T,
typename F>
576 template <
typename TEnum>
577 formats_builder& enum_type(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
579 template <
typename TEnum>
580 formats_builder& enum_type_icase(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
582 template <
typename TPo
inter>
585 template <
typename TPo
inter,
typename F>
588 template <
typename F>
595 formats_builder& reference_type(std::type_index type, std::type_index from);
597 template <
typename TOptional>
600 template <
typename TContainer>
603 #if JSONV_COMPILER_SUPPORTS_TEMPLATE_TEMPLATES 604 template <
typename T,
template <
class...>
class... TTContainers>
608 template <
typename TWrapper>
612 formats_builder& check_references(
const formats::list& others,
const std::string& name =
"");
617 formats compose_checked(
formats other,
const std::string& name =
"");
618 formats compose_checked(std::vector<formats> others,
const std::string& name =
"");
626 template <
typename T>
640 template <
typename TMember>
643 template <
typename TMember>
645 std::function<
const TMember& (
const T&)> access,
646 std::function<
void (T&, TMember&&)> mutate
649 template <
typename TMember>
651 const TMember& (T::*access)()
const,
652 TMember& (T::*mutable_access)()
655 template <
typename TMember>
657 const TMember& (T::*access)()
const,
658 void (T::*mutate)(TMember)
661 template <
typename TMember>
663 const TMember& (T::*access)()
const,
664 void (T::*mutate)(TMember&&)
667 adapter_builder<T>& pre_extract(
typename adapter_builder<T>::pre_extract_func perform);
669 adapter_builder<T>& post_extract(
typename adapter_builder<T>::post_extract_func perform);
671 adapter_builder<T>& on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler);
677 template <
typename T>
688 virtual bool has_extract_key(
string_view key)
const = 0;
691 template <
typename T,
typename TMember>
696 using mutator_type = std::function<void (T&, TMember&&)>;
697 using accessor_type = std::function<const TMember& (const T&)>;
700 explicit member_adapter_impl(std::string name, mutator_type mutator, accessor_type access) :
701 _names({ std::move(name) }),
702 _set_value(std::move(mutator)),
703 _get_value(std::move(access))
708 [selector] (T&
value, TMember&& x) { value.*selector = std::move(x); },
709 [selector] (
const T& value) ->
const TMember& {
return value.*selector; }
713 virtual void mutate(
const extraction_context& context,
const value& from, T& out)
const override 716 for (
const auto& name : _names)
720 bool use_default =
false;
723 use_default = bool(_default_value);
725 throw extraction_error(context, std::string(
"Missing required field ") + _names.at(0));
727 else if (_default_on_null && iter->second.kind() == kind::null)
733 _set_value(out, _default_value(context, from));
735 _set_value(out, context.
extract_sub<TMember>(from, iter->first));
740 if (should_encode(context, from))
741 out.
insert({ _names.at(0), context.
to_json(_get_value(from)) });
744 virtual bool has_extract_key(
string_view key)
const override 746 return std::any_of(begin(_names), end(_names), [key] (
const std::string& name) {
return name == key; });
753 auto old_check = std::move(_should_encode);
756 return check(context, value) && old_check(context, value);
761 _should_encode = std::move(
check);
765 void add_extraction_mutator(std::function <TMember (TMember&&)> mutate)
769 auto old_mutate = std::move(_extract_mutate);
770 _extract_mutate = [old_mutate, mutate] (TMember&& member) {
return mutate(old_mutate(std::move(member))); };
774 _extract_mutate = std::move(mutate);
778 void add_extraction_check(std::function <
void (
const TMember&)>
check)
780 add_extraction_mutator([
check] (TMember&& value)
787 void default_value(std::function<TMember (
const extraction_context&,
const value&)>&& create)
789 _default_value = std::move(create);
792 void default_on_null(
bool on)
794 _default_on_null = on;
801 return _should_encode(context, _get_value(from));
807 template <
typename U,
typename UMember>
811 std::vector<std::string> _names;
812 mutator_type _set_value;
813 accessor_type _get_value;
814 std::function<bool (const serialization_context&, const TMember&)> _should_encode;
815 std::function<TMember (const extraction_context&, const value&)> _default_value;
816 bool _default_on_null =
false;
817 std::function<TMember (TMember&&)> _extract_mutate;
822 template <
typename T,
typename TMember>
836 reference_type(std::type_index(
typeid(TMember)), std::type_index(
typeid(T)));
842 _adapter->_names.emplace_back(std::move(name));
848 _adapter->add_extraction_check(std::move(
check));
853 std::function<
void (
const TMember&)> thrower
856 _adapter->add_extraction_check([
check, thrower] (
const TMember&
value)
864 template <
typename TException>
867 return check_input(std::move(
check), [ex] (
const TMember&) {
throw ex; });
899 _adapter->add_encode_check(std::move(
check));
947 template <
typename T>
952 using pre_extract_func = std::function<void (const extraction_context&, const value&)>;
953 using post_extract_func = std::function<T (const extraction_context&, T&&)>;
954 using extra_keys_func = std::function<void (const extraction_context&, const value&, std::set<std::string>)>;
957 template <
typename F>
959 formats_builder_dsl(owner),
962 auto adapter = std::make_shared<adapter_impl>();
963 register_adapter(adapter);
964 _adapter = adapter.get();
966 std::forward<F>(f)(*
this);
975 _adapter->_default_on_null = on;
981 _adapter->_create_default = std::move(create);
990 template <
typename TMember>
993 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
998 _adapter->_members.emplace_back(std::move(ptr));
1002 template <
typename TMember>
1004 std::function<
const TMember& (
const T&)> access,
1005 std::function<
void (T&, TMember&&)> mutate
1008 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
1013 _adapter->_members.emplace_back(std::move(ptr));
1017 template <
typename TMember>
1019 const TMember& (T::*access)()
const,
1020 TMember& (T::*mutable_access)()
1023 return member<TMember>(std::move(name),
1025 [mutable_access] (T& x, TMember&& val) { (x.*mutable_access)() = std::move(val); }
1029 template <
typename TMember>
1031 const TMember& (T::*access)()
const,
1032 void (T::*mutate)(TMember)
1035 return member<TMember>(std::move(name),
1036 std::function<const TMember& (const T&)>(access),
1037 [mutate] (T& x, TMember val) { (x.*mutate)(std::move(val)); }
1041 template <
typename TMember>
1043 const TMember& (T::*access)()
const,
1044 void (T::*mutate)(TMember&&)
1047 return member<TMember>(std::move(name),
1048 std::function<const TMember& (const T&)>(access),
1049 std::function<
void (T&, TMember&&)>(mutate)
1055 if (_adapter->_pre_extract)
1057 pre_extract_func old_perform = std::move(_adapter->_pre_extract);
1058 _adapter->_pre_extract = [old_perform, perform] (
const extraction_context& context,
const value& from)
1060 old_perform(context, from);
1061 perform(context, from);
1066 _adapter->_pre_extract = std::move(perform);
1073 if (_adapter->_post_extract)
1075 post_extract_func old_perform = std::move(_adapter->_post_extract);
1076 _adapter->_post_extract = [old_perform, perform] (
const extraction_context& context, T&& out)
1078 return perform(context, old_perform(context, std::move(out)));
1083 _adapter->_post_extract = std::move(perform);
1090 adapter_impl* adapter = _adapter;
1091 return pre_extract([adapter, handler] (
const extraction_context& context,
const value& from)
1095 return std::any_of(begin(adapter->_members), end(adapter->_members),
1098 return mem->has_extract_key(key);
1102 std::set<std::string> extra_keys;
1103 for (
const auto& pair : from.
as_object())
1104 if (!is_key(pair.first))
1105 extra_keys.insert(pair.first);
1106 if (!extra_keys.empty())
1107 handler(context, from, std::move(extra_keys));
1112 class adapter_impl :
1117 _default_on_null(
false)
1120 virtual T create(
const extraction_context& context,
const value& from)
const override 1123 _pre_extract(context, from);
1125 if (_default_on_null && from.
is_null())
1126 return _create_default(context);
1129 for (
const auto& member : _members)
1130 member->mutate(context, from, out);
1133 out = _post_extract(context, std::move(out));
1141 for (
const auto& member : _members)
1142 member->to_json(context, from, out);
1146 std::deque<std::unique_ptr<detail::member_adapter<T>>> _members;
1147 pre_extract_func _pre_extract;
1148 post_extract_func _post_extract;
1149 std::function<T (const extraction_context&)> _create_default;
1150 bool _default_on_null;
1154 adapter_impl* _adapter;
1157 template <
typename TPo
inter>
1162 template <
typename F>
1164 std::string discrimination_key,
1167 formats_builder_dsl(owner),
1169 _discrimination_key(std::move(discrimination_key))
1171 auto adapter = std::make_shared<polymorphic_adapter<TPointer>>();
1172 register_adapter(adapter);
1173 _adapter = adapter.get();
1175 std::forward<F>(f)(*
this);
1180 std::move(discrimination_key),
1187 _adapter->check_null_input(on);
1193 _adapter->check_null_output(on);
1197 template <
typename TSub>
1201 if (_discrimination_key.empty())
1202 throw std::logic_error(
"Cannot use single-argument subtype if no discrimination_key has been set");
1204 return subtype<TSub>(_discrimination_key, std::move(discrimination_value), action);
1207 template <
typename TSub>
1209 value discrimination_value,
1212 _adapter->template add_subtype_keyed<TSub>(std::move(discrimination_key),
1213 std::move(discrimination_value),
1215 reference_type(std::type_index(
typeid(TSub)), std::type_index(
typeid(TPointer)));
1219 template <
typename TSub>
1222 _adapter->template add_subtype<TSub>(std::move(discriminator));
1223 reference_type(std::type_index(
typeid(TSub)), std::type_index(
typeid(TPointer)));
1227 template <
typename TSub>
1232 return discriminator(val);
1239 std::string _discrimination_key;
1247 template <
typename T>
1253 template <
typename T,
typename F>
1259 template <
typename TEnum>
1261 std::initializer_list<std::pair<TEnum, value>> mapping
1264 return register_adapter(std::make_shared<
enum_adapter<TEnum>>(std::move(enum_name), mapping));
1267 template <
typename TEnum>
1269 std::initializer_list<std::pair<TEnum, value>> mapping
1275 template <
typename TPo
inter>
1277 polymorphic_type(std::string discrimination_key =
"")
1282 template <
typename TPo
inter,
typename F>
1284 polymorphic_type(std::string discrimination_key, F&& f)
1289 template <
typename F>
1292 std::forward<F>(func)(*
this);
1298 _formats.register_adapter(p, _duplicate_type_action);
1304 _formats.register_adapter(std::move(p), _duplicate_type_action);
1308 template <
typename TOptional>
1311 reference_type(std::type_index(
typeid(
typename TOptional::value_type)), std::type_index(
typeid(TOptional)));
1313 _formats.register_adapter(std::move(p), _duplicate_type_action);
1317 template <
typename TContainer>
1320 reference_type(std::type_index(
typeid(
typename TContainer::value_type)), std::type_index(
typeid(TContainer)));
1322 _formats.register_adapter(std::move(p), _duplicate_type_action);
1326 template <
typename TWrapper>
1329 reference_type(std::type_index(
typeid(
typename TWrapper::value_type)), std::type_index(
typeid(TWrapper)));
1331 _formats.register_adapter(std::move(p), _duplicate_type_action);
1335 #if JSONV_COMPILER_SUPPORTS_TEMPLATE_TEMPLATES 1336 template <
typename T>
1342 template <
typename T,
template <
class...>
class TTContainer,
template <
class...>
class... TTRest>
1345 register_container<TTContainer<T>>();
1346 return register_containers<T, TTRest...>();
1356 formats_builder& reference_type(std::type_index type, std::type_index from);
1369 formats_builder& check_references(
const formats::list& others,
const std::string& name =
"");
1376 formats compose_checked(
formats other,
const std::string& name =
"");
1377 formats compose_checked(
const formats::list& others,
const std::string& name =
"");
1386 void check_references_impl(
const formats& searching,
const std::string& name);
1391 std::map<std::type_index, std::set<std::type_index>> _referenced_types;
1397 template <
typename T>
1400 return owner->type<T>();
1403 template <
typename T,
typename F>
1406 return owner->type<T>(std::forward<F>(f));
1409 template <
typename TEnum>
1410 formats_builder& formats_builder_dsl::enum_type(std::string enum_name,
1411 std::initializer_list<std::pair<TEnum, value>> mapping
1414 return owner->enum_type<TEnum>(std::move(enum_name), mapping);
1417 template <
typename TEnum>
1418 formats_builder& formats_builder_dsl::enum_type_icase(std::string enum_name,
1419 std::initializer_list<std::pair<TEnum, value>> mapping
1422 return owner->enum_type_icase<TEnum>(std::move(enum_name), mapping);
1425 template <
typename TPo
inter>
1427 formats_builder_dsl::polymorphic_type(std::string discrimination_key)
1429 return owner->polymorphic_type<TPointer>(std::move(discrimination_key));
1432 template <
typename TPo
inter,
typename F>
1434 formats_builder_dsl::polymorphic_type(std::string discrimination_key, F&& f)
1436 return owner->polymorphic_type<TPointer>(std::move(discrimination_key), std::forward<F>(f));
1439 template <
typename F>
1442 return owner->extend(std::forward<F>(f));
1445 template <
typename TOptional>
1448 return owner->register_optional<TOptional>();
1451 template <
typename TContainer>
1454 return owner->register_container<TContainer>();
1457 #if JSONV_COMPILER_SUPPORTS_TEMPLATE_TEMPLATES 1458 template <
typename T,
template <
class...>
class... TTContainers>
1461 return owner->register_containers<T, TTContainers...>();
1465 template <
typename TWrapper>
1468 return owner->register_container<TWrapper>();
1471 template <
typename T>
1474 return owner->type_default_on_null(on);
1477 template <
typename T>
1480 return owner->type_default_value(std::move(create));
1483 template <
typename T>
1486 return owner->type_default_value(value);
1489 template <
typename T>
1490 template <
typename TMember>
1493 return owner->member(std::move(name), selector);
1496 template <
typename T>
1497 template <
typename TMember>
1499 adapter_builder_dsl<T>::member(std::string name,
1500 std::function<
const TMember& (
const T&)> access,
1501 std::function<
void (T&, TMember&&)> mutate
1504 return owner->member(std::move(name), std::move(access), std::move(mutate));
1507 template <
typename T>
1508 template <
typename TMember>
1510 adapter_builder_dsl<T>::member(std::string name,
1511 const TMember& (T::*access)()
const,
1512 TMember& (T::*mutable_access)()
1515 return owner->member(std::move(name), access, mutable_access);
1518 template <
typename T>
1519 template <
typename TMember>
1521 adapter_builder_dsl<T>::member(std::string name,
1522 const TMember& (T::*access)()
const,
1523 void (T::*mutate)(TMember)
1526 return owner->member(std::move(name), access, mutate);
1529 template <
typename T>
1530 template <
typename TMember>
1532 adapter_builder_dsl<T>::member(std::string name,
1533 const TMember& (T::*access)()
const,
1534 void (T::*mutate)(TMember&&)
1537 return owner->member(std::move(name), access, mutate);
1540 template <
typename T>
1541 adapter_builder<T>& adapter_builder_dsl<T>::pre_extract(
typename adapter_builder<T>::pre_extract_func perform)
1543 return owner->pre_extract(std::move(perform));
1546 template <
typename T>
1547 adapter_builder<T>& adapter_builder_dsl<T>::post_extract(
typename adapter_builder<T>::post_extract_func perform)
1549 return owner->post_extract(std::move(perform));
1552 template <
typename T>
1553 adapter_builder<T>& adapter_builder_dsl<T>::on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler)
1555 return owner->on_extract_extra_keys(std::move(handler));
1567 const std::set<std::string>& extra_keys
#define JSONV_NO_RETURN
Mark that a given function will never return control to the caller, either by exiting or throwing an ...
An adapter for container types.
object_iterator end_object()
Get an iterator to the one past the end of this object.
member_adapter_builder & default_on_null(bool on=true)
Should a kind::null for a key be interpreted as a missing value?
Don't do any checking or insertion of the expected key/value pair.
A duplicate_type_error should be thrown.
member_adapter_builder & after(version ver)
Only encode this member if the serialization_context::version is greater than ver.
array_iterator insert(const_array_iterator position, value item)
Insert an item into position on this array.
bool is_null() const
Tests if this kind is kind::null.
JSONV_PUBLIC JSONV_NO_RETURN 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.
Helper types and functions for serialization.
member_adapter_builder & encode_if(std::function< bool(const serialization_context &, const TMember &)> check)
Only encode this member if the check passes.
Copyright (c) 2014-2019 by Travis Gockel.
object_view as_object()&
View this instance as an object.
An adapter is both an extractor and a serializer.
constexpr bool empty() const
Check if this version is an "empty" value – meaning major and minor are both 0.
An adapter for optional-like types.
An adapter which can create polymorphic types.
object_iterator find(const std::string &key)
Attempt to locate a key-value pair with the provided key in this object.
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...
const jsonv::version version() const
Get the version this extraction_context was created with.
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 & default_value(TMember value)
If the key for this member is not in the object when deserializing, use this value.
keyed_subtype_action
What to do when serializing a keyed subtype of a polymorphic_adapter.
An adapter for enumeration types.
Conversion between C++ types and JSON values.
member_adapter_builder & alternate_name(std::string name)
When extracting, also look for this name as a key.
An adapter for "wrapper" types.
Represents a version used to extract and encode JSON objects from C++ classes.
JSONV_PUBLIC value object()
Create an empty object.
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.
value to_json(const T &from) const
Convenience function for converting a C++ object into a JSON value.
A non-owning reference to an std::string, as proposed to the C++ Standard Committee by Jeffrey Yasski...
#define JSONV_PUBLIC
This function or class is part of the public API for JsonVoorhees.
member_adapter_builder & until(version ver)
Only encode this member if the serialization_context::version is less than or equal to ver...
JSONV_STRING_VIEW_TYPE string_view
A non-owning reference to a string.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
duplicate_type_action
The action to take when an insertion of an extractor or serializer into a formats is attempted...