683class formats_builder;
685template <
typename T>
class adapter_builder;
686template <
typename T,
typename TMember>
class member_adapter_builder;
687template <
typename TPo
inter>
class polymorphic_adapter_builder;
692class formats_builder_dsl
695 explicit formats_builder_dsl(formats_builder* owner) :
699 template <
typename T>
700 adapter_builder<T> type();
702 template <
typename T,
typename F>
703 adapter_builder<T> type(F&&);
705 template <
typename TEnum>
706 formats_builder& enum_type(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
708 template <
typename TEnum>
709 formats_builder& enum_type_icase(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
711 template <
typename TPo
inter>
712 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key =
"");
714 template <
typename TPo
inter,
typename F>
715 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key, F&&);
717 template <
typename F>
718 formats_builder& extend(F&&);
720 formats_builder& register_adapter(
const adapter* p);
721 formats_builder& register_adapter(std::shared_ptr<const adapter> p);
723 formats_builder& reference_type(std::type_index typ);
724 formats_builder& reference_type(std::type_index type, std::type_index from);
726 template <
typename TOptional>
727 formats_builder& register_optional();
729 template <
typename TContainer>
730 formats_builder& register_container();
732 template <
typename T,
template <
class...>
class... TTContainers>
733 formats_builder& register_containers();
735 template <
typename TWrapper>
736 formats_builder& register_wrapper();
738 formats_builder& check_references(
const formats& other,
const std::string& name =
"");
739 formats_builder& check_references(
const formats::list& others,
const std::string& name =
"");
740 formats_builder& check_references(
const std::string& name =
"");
745 formats compose_checked(formats other,
const std::string& name =
"");
747 formats compose_checked(std::vector<formats> others,
const std::string& name =
"");
750 operator formats()
const;
753 formats_builder* owner;
757class adapter_builder_dsl
760 explicit adapter_builder_dsl(adapter_builder<T>* owner) :
764 adapter_builder<T>& type_default_on_null(
bool on =
true);
766 adapter_builder<T>& type_default_value(std::function<T (deserialization_context& ctx)> create);
768 adapter_builder<T>& type_default_value(
const T& value);
770 template <
typename TMember>
771 member_adapter_builder<T, TMember> member(std::string name, TMember T::*selector);
773 template <
typename TMember>
774 member_adapter_builder<T, TMember> member(std::string name,
775 std::function<
const TMember& (
const T&)> access,
776 std::function<
void (T&, TMember&&)> mutate
779 template <
typename TMember>
780 member_adapter_builder<T, TMember> member(std::string name,
781 const TMember& (T::*access)() const,
782 TMember& (T::*mutable_access)()
785 template <
typename TMember>
786 member_adapter_builder<T, TMember> member(std::string name,
787 const TMember& (T::*access)() const,
788 void (T::*mutate)(TMember)
791 template <
typename TMember>
792 member_adapter_builder<T, TMember> member(std::string name,
793 const TMember& (T::*access)() const,
794 void (T::*mutate)(TMember&&)
797 adapter_builder<T>& pre_deserialize(
typename adapter_builder<T>::pre_deserialize_func perform);
799 adapter_builder<T>& post_deserialize(
typename adapter_builder<T>::post_deserialize_func perform);
801 adapter_builder<T>& on_unknown_members(
typename adapter_builder<T>::unknown_members_func handler);
804 adapter_builder<T>* owner;
813inline bool current_is_null(
const reader& from)
815 if (
auto lent = from.current_value())
816 return lent->kind() == jsonv::kind::null;
818 return from.good() && from.current_type() == ast_node_type::literal_null;
822constexpr std::size_t no_deserialize_key = std::size_t(-1);
839class member_claim_set
843 static constexpr std::uint16_t unclaimed = std::uint16_t(-1);
846 explicit member_claim_set(std::size_t count)
848 if (count > inline_capacity)
850 _spilled = std::make_unique<spilled_claim[]>(count);
851 std::fill_n(_spilled.get(), count, spilled_claim{ unclaimed, false });
855 _ranks.fill(unclaimed);
861 std::uint16_t claim_rank(std::size_t idx)
const
863 return _spilled ? _spilled[idx].rank : _ranks[idx];
867 bool claimed(std::size_t idx)
const
869 return claim_rank(idx) != unclaimed;
875 bool wants_default(std::size_t idx)
const
880 return _spilled[idx].null_default;
882 return (_null_defaults >> idx & 1U) != 0U;
887 void claim(std::size_t idx, std::size_t rank,
bool null_default =
false)
891 auto stored = std::uint16_t(std::min<std::size_t>(rank, unclaimed - 1U));
895 _spilled[idx] = spilled_claim{ stored, null_default };
899 _ranks[idx] = stored;
901 const auto bit = std::uint64_t(1U) << idx;
902 _null_defaults = null_default ? (_null_defaults | bit) : (_null_defaults & ~bit);
907 static constexpr std::size_t inline_capacity = 64U;
908 static_assert(inline_capacity <= 64U,
"_null_defaults has a bit for each member tracked inline");
920 std::array<std::uint16_t, inline_capacity> _ranks;
924 std::uint64_t _null_defaults = 0U;
925 std::unique_ptr<spilled_claim[]> _spilled;
932 virtual ~member_adapter() noexcept
944 virtual std::expected<void, ast_node_type>
945 deserialize(deserialization_context& context, reader& from, std::string_view key, T& out)
const = 0;
950 virtual std::expected<void, ast_node_type> apply_default(deserialization_context& context, T& out)
const = 0;
956 virtual bool defaults_on_null()
const = 0;
962 virtual void serialize(
const serialization_context& context,
const T& from, writer& to)
const = 0;
966 virtual bool has_default()
const = 0;
975 virtual std::size_t deserialize_key_rank(std::string_view key)
const = 0;
980 virtual std::string_view primary_name()
const = 0;
983template <
typename T,
typename TMember>
984class member_adapter_impl :
985 public member_adapter<T>
988 using mutator_type = std::function<void (T&, TMember&&)>;
989 using accessor_type = std::function<
const TMember& (
const T&)>;
992 explicit member_adapter_impl(std::string name, mutator_type mutator, accessor_type access) :
993 _names({ std::move(name) }),
994 _set_value(std::move(mutator)),
995 _get_value(std::move(access))
998 explicit member_adapter_impl(std::string name, TMember T::*selector) :
999 member_adapter_impl(
std::move(name),
1000 [selector] (T& value, TMember&& x) { value.*selector = std::move(x); },
1001 [selector] (
const T& value) ->
const TMember& {
return value.*selector; }
1006 virtual std::expected<void, ast_node_type>
1007 deserialize(deserialization_context& context, reader& from, std::string_view key, T& out)
const override
1016 auto deserialized = [&] () -> std::expected<TMember, ast_node_type>
1018 deserialization_context::path_scope scope(context, key);
1020 return context.deserialize<TMember>(from);
1024 return std::unexpected(deserialized.error());
1028 if (_deserialize_mutate)
1029 _set_value(out, _deserialize_mutate(*std::move(deserialized)));
1031 _set_value(out, *std::move(deserialized));
1037 virtual std::expected<void, ast_node_type> apply_default(deserialization_context& context, T& out)
const override
1039 _set_value(out, _default_value(context));
1043 virtual void serialize(
const serialization_context& context,
const T& from, writer& to)
const override
1045 const TMember& member = _get_value(from);
1046 if (!_should_serialize || _should_serialize(context, member))
1048 to.key(_names.at(0));
1049 context.serialize(member, to);
1054 virtual bool has_default()
const override
1056 return bool(_default_value);
1060 virtual bool defaults_on_null()
const override
1062 return _default_on_null && _default_value;
1066 virtual std::size_t deserialize_key_rank(std::string_view key)
const override
1068 for (std::size_t rank = 0U; rank < _names.size(); ++rank)
1069 if (_names[rank] == key)
1072 return no_deserialize_key;
1076 virtual std::string_view primary_name()
const override
1078 return _names.at(0);
1081 void add_serialize_check(std::function<
bool (
const serialization_context&,
const TMember&)>
check)
1083 if (_should_serialize)
1085 auto old_check = std::move(_should_serialize);
1086 _should_serialize = [
check, old_check] (
const serialization_context& context,
const TMember& value)
1088 return check(context, value) && old_check(context, value);
1093 _should_serialize = std::move(
check);
1097 void add_deserialization_mutator(std::function <TMember (TMember&&)> mutate)
1099 if (_deserialize_mutate)
1101 auto old_mutate = std::move(_deserialize_mutate);
1102 _deserialize_mutate = [old_mutate, mutate] (TMember&& member)
1104 return mutate(old_mutate(std::move(member)));
1109 _deserialize_mutate = std::move(mutate);
1113 void add_deserialization_check(std::function <
void (
const TMember&)>
check)
1115 add_deserialization_mutator([
check] (TMember&& value)
1122 void default_value(std::function<TMember (deserialization_context&)>&& create)
1124 _default_value = std::move(create);
1127 void default_on_null(
bool on)
1129 _default_on_null = on;
1136 template <
typename U,
typename UMember>
1140 std::vector<std::string> _names;
1141 mutator_type _set_value;
1142 accessor_type _get_value;
1143 std::function<bool (
const serialization_context&,
const TMember&)> _should_serialize;
1144 std::function<TMember (deserialization_context&)> _default_value;
1145 bool _default_on_null =
false;
1146 std::function<TMember (TMember&&)> _deserialize_mutate;
1151template <
typename T,
typename TMember>
1153 public detail::formats_builder_dsl,
1154 public detail::adapter_builder_dsl<T>
1159 detail::member_adapter_impl<T, TMember>*
adapter
1161 formats_builder_dsl(fmt_builder),
1162 detail::adapter_builder_dsl<T>(adapt_builder),
1165 reference_type(std::type_index(
typeid(TMember)), std::type_index(
typeid(T)));
1171 _adapter->_names.emplace_back(std::move(name));
1177 _adapter->add_deserialization_check(std::move(inspect));
1181 member_adapter_builder&
check(std::function<
bool (
const TMember&)> accept,
1182 std::function<
void (
const TMember&)> thrower
1185 _adapter->add_deserialization_check([accept = std::move(accept), thrower = std::move(thrower)]
1186 (
const TMember& value)
1198 template <
typename TException>
1199 requires (!std::invocable<TException&, const TMember&>)
1202 return check(std::move(accept), [ex = std::move(ex)] (
const TMember&) {
throw ex; });
1210 _adapter->default_value(std::move(create));
1227 _adapter->default_on_null(on);
1236 _adapter->add_serialize_check(std::move(
check));
1285 detail::member_adapter_impl<T, TMember>* _adapter;
1288template <
typename T>
1290 public detail::formats_builder_dsl
1298 template <
typename F>
1300 formats_builder_dsl(owner),
1303 auto adapter = std::make_shared<adapter_impl>();
1307 std::forward<F>(f)(*this);
1316 _adapter->_default_on_null = on;
1322 _adapter->_create_default = std::move(create);
1332 template <
typename TMember>
1335 return add_member(std::make_unique<detail::member_adapter_impl<T, TMember>>(std::move(name), selector));
1339 template <
typename TMember>
1341 std::function<
const TMember& (
const T&)> access,
1342 std::function<
void (T&, TMember&&)> mutate
1345 return add_member(std::make_unique<detail::member_adapter_impl<T, TMember>>(std::move(name),
1351 template <
typename TMember>
1353 const TMember& (T::*access)() const,
1354 TMember& (T::*mutable_access)()
1357 return member<TMember>(std::move(name),
1359 [mutable_access] (T& x, TMember&& val) { (x.*mutable_access)() = std::move(val); }
1363 template <
typename TMember>
1364 member_adapter_builder<T, TMember>
member(std::string name,
1365 const TMember& (T::*access)() const,
1366 void (T::*mutate)(TMember)
1369 return member<TMember>(std::move(name),
1370 std::function<
const TMember& (
const T&)>(access),
1371 [mutate] (T& x, TMember val) { (x.*mutate)(std::move(val)); }
1375 template <
typename TMember>
1376 member_adapter_builder<T, TMember>
member(std::string name,
1377 const TMember& (T::*access)() const,
1378 void (T::*mutate)(TMember&&)
1381 return member<TMember>(std::move(name),
1382 std::function<
const TMember& (
const T&)>(access),
1383 std::function<
void (T&, TMember&&)>(mutate)
1387 adapter_builder<T>& pre_deserialize(pre_deserialize_func perform)
1389 if (_adapter->_pre_deserialize)
1391 pre_deserialize_func old_perform = std::move(_adapter->_pre_deserialize);
1392 _adapter->_pre_deserialize = [old_perform, perform] (deserialization_context& context)
1394 old_perform(context);
1400 _adapter->_pre_deserialize = std::move(perform);
1405 adapter_builder<T>& post_deserialize(post_deserialize_func perform)
1407 if (_adapter->_post_deserialize)
1409 post_deserialize_func old_perform = std::move(_adapter->_post_deserialize);
1410 _adapter->_post_deserialize = [old_perform, perform] (deserialization_context& context, T&& out)
1412 return perform(context, old_perform(context, std::move(out)));
1417 _adapter->_post_deserialize = std::move(perform);
1428 if (_adapter->_unknown_members)
1430 unknown_members_func old_handler = std::move(_adapter->_unknown_members);
1431 _adapter->_unknown_members = [old_handler, handler]
1435 handler(
context, std::move(keys));
1440 _adapter->_unknown_members = std::move(handler);
1453 template <
typename TMember>
1456 for (
const auto& existing : _adapter->_members)
1457 if (existing->primary_name() == ptr->primary_name())
1458 throw
std::invalid_argument(
"Member \"" +
std::string(ptr->primary_name())
1459 +
"\" is already declared for " +
demangle(typeid(T).name())
1463 _adapter->_members.emplace_back(std::move(ptr));
1468 class adapter_impl :
1469 public adapter_for<T>
1473 _default_on_null(false)
1477 virtual std::expected<T, ast_node_type> create(deserialization_context& context, reader& from)
const override
1481 detail::source_scope source(context, from);
1483 if (_pre_deserialize)
1484 _pre_deserialize(context);
1487 if (_default_on_null && _create_default && detail::current_is_null(from))
1492 (void) from.next_token();
1496 return _create_default(context);
1503 context.note_value_consumed(from);
1508 auto opened = context.current_as<ast_node::object_begin>(from);
1510 return std::unexpected(opened.error());
1512 source.open(from, *opened);
1515 detail::member_claim_set claims(_members.size());
1516 bool recovered =
false;
1517 bool closed =
false;
1522 std::optional<std::set<std::string>> unknown_members;
1523 std::optional<std::set<std::string>> repeated_keys;
1530 repeated_keys.emplace();
1535 (void) from.next_token();
1541 auto type = from.current_type();
1543 if (type == ast_node_type::document_end || type == ast_node_type::error)
1547 return context.problem(context.problem_path(from),
"Unterminated object");
1549 else if (type == ast_node_type::object_end)
1564 std::optional<std::string> decoded;
1565 std::string_view key;
1566 if (type == ast_node_type::key_canonical)
1568 key = from.current().as<ast_node::key_canonical>().value();
1570 else if (type == ast_node_type::key_escaped)
1572 key = decoded.emplace(from.current().as<ast_node::key_escaped>().value());
1576 auto matched = context.expect(from,
1577 { ast_node_type::key_canonical, ast_node_type::key_escaped }
1579 return std::unexpected(matched.error());
1582 if (!from.next_token())
1583 return context.problem(context.problem_path(from),
"Unterminated object");
1585 if (repeated_keys && !repeated_keys->emplace(key).second)
1590 std::string message(
"Duplicate key in object: \"");
1591 message.append(key);
1592 message.append(
"\"");
1594 (void) context.problem(context.path(), std::move(message));
1596 if (!context.recover())
1597 return std::unexpected(ast_node_type::error);
1600 (void) from.next_value();
1604 auto matched = find_member(key);
1605 if (matched.index == _members.size())
1609 if (_unknown_members)
1611 if (!unknown_members)
1612 unknown_members.emplace();
1614 unknown_members->emplace(key);
1617 (void) from.next_value();
1621 if (
auto held = claims.claim_rank(matched.index); held != detail::member_claim_set::unclaimed)
1623 if (matched.rank > held)
1629 (void) from.next_value();
1632 else if (matched.rank == held && !consume_duplicate(context, from))
1641 const auto&
member = *_members[matched.index];
1642 if (
member.defaults_on_null() && detail::current_is_null(from))
1648 (void) from.next_token();
1649 claims.claim(matched.index, matched.rank,
true);
1653 auto walked = run_member(context,
1656 [&] {
return member.deserialize(context, from, key, out); }
1660 claims.claim(matched.index, matched.rank);
1663 return std::unexpected(walked.error());
1669 return context.problem(context.problem_path(from),
"Unterminated object");
1673 if (_unknown_members && unknown_members && !unknown_members->empty())
1674 _unknown_members(context, *std::move(unknown_members));
1676 for (std::size_t idx = 0U; idx < _members.size(); ++idx)
1678 if (!claims.wants_default(idx))
1681 const auto&
member = *_members[idx];
1682 if (!
member.has_default())
1684 std::string message(
"Missing required field ");
1685 message.append(
member.primary_name());
1687 (void) context.problem(context.path(), std::move(message));
1688 if (!context.recover())
1689 return std::unexpected(ast_node_type::error);
1697 auto applied = run_member(context,
1700 [&] {
return member.apply_default(context, out); }
1704 return std::unexpected(applied.error());
1716 walk_to_close(from);
1724 return std::unexpected(ast_node_type::error);
1726 if (_post_deserialize)
1727 out = _post_deserialize(context, std::move(out));
1730 (void) from.next_token();
1740 context.note_value_consumed(from);
1745 virtual void serialize(
const serialization_context& context,
const T& from, writer& to)
const override
1750 for (
const auto&
member : _members)
1755 std::deque<std::unique_ptr<detail::member_adapter<T>>> _members;
1756 pre_deserialize_func _pre_deserialize;
1757 post_deserialize_func _post_deserialize;
1758 unknown_members_func _unknown_members;
1759 std::function<T (deserialization_context&)> _create_default;
1760 bool _default_on_null;
1778 member_match find_member(std::string_view key)
const
1780 for (std::size_t idx = 0U; idx < _members.size(); ++idx)
1781 if (
auto rank = _members[idx]->deserialize_key_rank(key); rank != detail::no_deserialize_key)
1782 return member_match{ idx, rank };
1784 return member_match{ _members.size(), detail::no_deserialize_key };
1797 static bool consume_duplicate(deserialization_context& context, reader& from)
1801 (void) from.next_value();
1820 template <
typename FRun>
1822 static std::expected<bool, ast_node_type> run_member(deserialization_context& context,
1823 const detail::member_adapter<T>&
member,
1830 if (
auto result = run())
1834 else if (!context.recover())
1836 return std::unexpected(result.error());
1840 context.skip_failed_value(*from);
1843 catch (
const deserialization_error& ex)
1847 if (!context.recover(ex))
1850 catch (
const std::bad_alloc&)
1869 deserialization_context::path_scope scope(context,
member.primary_name());
1870 deserialization_error translated(context.path(), std::current_exception());
1872 if (!context.recover(translated))
1883 static void walk_to_close(reader& from)
noexcept
1887 auto type = from.current_type();
1888 if ( type == ast_node_type::object_end
1889 || type == ast_node_type::document_end
1890 || type == ast_node_type::error
1895 else if (type == ast_node_type::key_canonical || type == ast_node_type::key_escaped)
1898 (void) from.next_key();
1902 (void) from.next_value();
1909 adapter_impl* _adapter;
1912template <
typename TPo
inter>
1914 public detail::formats_builder_dsl
1917 template <
typename F>
1919 std::string discrimination_key,
1922 formats_builder_dsl(owner),
1924 _discrimination_key(std::move(discrimination_key))
1926 auto adapter = std::make_shared<polymorphic_adapter<TPointer>>();
1930 std::forward<F>(f)(*this);
1935 std::move(discrimination_key),
1942 _adapter->check_null_input(on);
1948 _adapter->check_null_output(on);
1952 template <
typename TSub>
1956 if (_discrimination_key.empty())
1957 throw std::logic_error(
"Cannot use single-argument subtype if no discrimination_key has been set");
1959 return subtype<TSub>(_discrimination_key, std::move(discrimination_value), action);
1962 template <
typename TSub>
1964 value discrimination_value,
1967 _adapter->template add_subtype_keyed<TSub>(std::move(discrimination_key),
1968 std::move(discrimination_value),
1970 reference_type(std::type_index(
typeid(TSub)), std::type_index(
typeid(TPointer)));
1974 template <
typename TSub>
1977 _adapter->template add_subtype<TSub>(std::move(discriminator));
1978 reference_type(std::type_index(
typeid(TSub)), std::type_index(
typeid(TPointer)));
1982 template <
typename TSub>
1987 return discriminator(val);
1994 std::string _discrimination_key;
2002 template <
typename T>
2008 template <
typename T,
typename F>
2014 template <
typename TEnum>
2016 std::initializer_list<std::pair<TEnum, value>> mapping
2019 return register_adapter(std::make_shared<
enum_adapter<TEnum>>(std::move(enum_name), mapping));
2022 template <
typename TEnum>
2024 std::initializer_list<std::pair<TEnum, value>> mapping
2030 template <
typename TPo
inter>
2032 polymorphic_type(std::string discrimination_key =
"")
2037 template <
typename TPo
inter,
typename F>
2039 polymorphic_type(std::string discrimination_key, F&& f)
2044 template <
typename F>
2047 std::forward<F>(func)(*this);
2053 _formats.register_adapter(p, _duplicate_type_action);
2059 _formats.register_adapter(std::move(p), _duplicate_type_action);
2063 template <
typename TOptional>
2066 reference_type(std::type_index(
typeid(
typename TOptional::value_type)), std::type_index(
typeid(TOptional)));
2068 _formats.register_adapter(std::move(p), _duplicate_type_action);
2072 template <
typename TContainer>
2075 reference_type(std::type_index(
typeid(
typename TContainer::value_type)), std::type_index(
typeid(TContainer)));
2077 _formats.register_adapter(std::move(p), _duplicate_type_action);
2081 template <
typename TWrapper>
2084 reference_type(std::type_index(
typeid(
typename TWrapper::value_type)), std::type_index(
typeid(TWrapper)));
2086 _formats.register_adapter(std::move(p), _duplicate_type_action);
2090 template <
typename T>
2096 template <
typename T,
template <
class...>
class TTContainer,
template <
class...>
class... TTRest>
2099 register_container<TTContainer<T>>();
2100 return register_containers<T, TTRest...>();
2110 formats_builder& reference_type(std::type_index type, std::type_index from);
2144 void check_references_impl(
const formats& searching,
const std::string& name);
2149 std::map<std::type_index, std::set<std::type_index>> _referenced_types;
2155template <
typename T>
2158 return owner->type<T>();
2161template <
typename T,
typename F>
2162adapter_builder<T> formats_builder_dsl::type(F&& f)
2164 return owner->type<T>(std::forward<F>(f));
2167template <
typename TEnum>
2168formats_builder& formats_builder_dsl::enum_type(std::string enum_name,
2169 std::initializer_list<std::pair<TEnum, value>> mapping
2172 return owner->enum_type<TEnum>(std::move(enum_name), mapping);
2175template <
typename TEnum>
2176formats_builder& formats_builder_dsl::enum_type_icase(std::string enum_name,
2177 std::initializer_list<std::pair<TEnum, value>> mapping
2180 return owner->enum_type_icase<TEnum>(std::move(enum_name), mapping);
2183template <
typename TPo
inter>
2184polymorphic_adapter_builder<TPointer>
2185formats_builder_dsl::polymorphic_type(std::string discrimination_key)
2187 return owner->polymorphic_type<TPointer>(std::move(discrimination_key));
2190template <
typename TPo
inter,
typename F>
2191polymorphic_adapter_builder<TPointer>
2192formats_builder_dsl::polymorphic_type(std::string discrimination_key, F&& f)
2194 return owner->polymorphic_type<TPointer>(std::move(discrimination_key), std::forward<F>(f));
2197template <
typename F>
2198formats_builder& formats_builder_dsl::extend(F&& f)
2200 return owner->extend(std::forward<F>(f));
2203template <
typename TOptional>
2204formats_builder& formats_builder_dsl::register_optional()
2206 return owner->register_optional<TOptional>();
2209template <
typename TContainer>
2210formats_builder& formats_builder_dsl::register_container()
2212 return owner->register_container<TContainer>();
2215template <
typename T,
template <
class...>
class... TTContainers>
2216formats_builder& formats_builder_dsl::register_containers()
2218 return owner->register_containers<T, TTContainers...>();
2221template <
typename TWrapper>
2222formats_builder& formats_builder_dsl::register_wrapper()
2224 return owner->register_wrapper<TWrapper>();
2227template <
typename T>
2228adapter_builder<T>& adapter_builder_dsl<T>::type_default_on_null(
bool on)
2230 return owner->type_default_on_null(on);
2233template <
typename T>
2234adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(std::function<T (deserialization_context& ctx)> create)
2236 return owner->type_default_value(std::move(create));
2239template <
typename T>
2240adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(
const T& value)
2242 return owner->type_default_value(value);
2245template <
typename T>
2246template <
typename TMember>
2247member_adapter_builder<T, TMember> adapter_builder_dsl<T>::member(std::string name, TMember T::*selector)
2249 return owner->member(std::move(name), selector);
2252template <
typename T>
2253template <
typename TMember>
2254member_adapter_builder<T, TMember>
2255adapter_builder_dsl<T>::member(std::string name,
2256 std::function<
const TMember& (
const T&)> access,
2257 std::function<
void (T&, TMember&&)> mutate
2260 return owner->member(std::move(name), std::move(access), std::move(mutate));
2263template <
typename T>
2264template <
typename TMember>
2265member_adapter_builder<T, TMember>
2266adapter_builder_dsl<T>::member(std::string name,
2267 const TMember& (T::*access)() const,
2268 TMember& (T::*mutable_access)()
2271 return owner->member(std::move(name), access, mutable_access);
2274template <
typename T>
2275template <
typename TMember>
2276member_adapter_builder<T, TMember>
2277adapter_builder_dsl<T>::member(std::string name,
2278 const TMember& (T::*access)() const,
2279 void (T::*mutate)(TMember)
2282 return owner->member(std::move(name), access, mutate);
2285template <
typename T>
2286template <
typename TMember>
2287member_adapter_builder<T, TMember>
2288adapter_builder_dsl<T>::member(std::string name,
2289 const TMember& (T::*access)() const,
2290 void (T::*mutate)(TMember&&)
2293 return owner->member(std::move(name), access, mutate);
2296template <
typename T>
2298adapter_builder_dsl<T>::pre_deserialize(
typename adapter_builder<T>::pre_deserialize_func perform)
2300 return owner->pre_deserialize(std::move(perform));
2303template <
typename T>
2305adapter_builder_dsl<T>::post_deserialize(
typename adapter_builder<T>::post_deserialize_func perform)
2307 return owner->post_deserialize(std::move(perform));
2310template <
typename T>
2312adapter_builder_dsl<T>::on_unknown_members(
typename adapter_builder<T>::unknown_members_func handler)
2314 return owner->on_unknown_members(std::move(handler));
2325 const std::set<std::string>& unknown_members
member_adapter_builder< T, TMember > member(std::string name, TMember T::*selector)
member_adapter_builder< T, TMember > member(std::string name, std::function< const TMember &(const T &)> access, std::function< void(T &, TMember &&)> mutate)
adapter_builder< T > & on_unknown_members(unknown_members_func handler)
The handler is stored rather than desugared into a pre_deserialize, because the keys which claimed no...
virtual void serialize(const serialization_context &context, const void *from, writer &to) const override
An adapter is both a deserializer and a serializer.
An adapter for container types.
Provides extra information to routines used for deserialization and serialization.
const std::optional< jsonv::version > & version() const
Get the version this context was created with.
Provides extra information to routines used for deserialization, collects the problems they encounter...
@ collect_all
Keep deserializing past a problem wherever something knows how to resume, so the deserialization_erro...
@ exception
Repeated keys should raise a deserialization_error.
@ ignore
Ignore the new values.
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 & alias(std::string name)
When deserializing, also look for this name as a key.
member_adapter_builder & default_value(std::function< TMember(deserialization_context &)> create)
If the key for this member is not in the object when deserializing, call this function to create a va...
member_adapter_builder & since(version ver)
Only serialize this member if the serialization_context was not created with a version,...
member_adapter_builder & default_on_null(bool on=true)
Should a kind::null for a key be interpreted as a missing value? Only considered if a default_value w...
member_adapter_builder & after(version ver)
Only serialize this member if the serialization_context was not created with a version,...
member_adapter_builder & serialize_if(std::function< bool(const serialization_context &, const TMember &)> check)
Only serialize this member if the check passes.
member_adapter_builder & before(version ver)
Only serialize this member if the serialization_context was not created with a version,...
member_adapter_builder & until(version ver)
Only serialize this member if the serialization_context was not created with a version,...
member_adapter_builder & check(std::function< bool(const TMember &)> accept, TException ex)
Constrained to a TException which cannot be called with the value as a non-const lvalue,...
An adapter for optional-like types.
An adapter which can create polymorphic types.
Provides extra information to routines used for serialization: the formats to find other serializers ...
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
An adapter for "wrapper" types.
Copyright (c) 2014-2020 by Travis Gockel.
Copyright (c) 2015-2026 by Travis Gockel.
Copyright (c) 2015 by Travis Gockel.
Copyright (c) 2015-2026 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_NODISCARD
Warn if the caller discards the result of this function.
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
JSONV_PUBLIC std::string demangle(std::string_view source)
Convert the input source from a mangled type into a human-friendly version.
duplicate_type_action
The action to take when an insertion of a deserializer or serializer into a formats is attempted,...
std::string serialize(const T &from, const formats &fmts=formats::global())
Serialize from into JSON text using fmts (by default jsonv::formats::global()).
keyed_subtype_action
What to do when serializing a keyed subtype of a polymorphic_adapter.
T deserialize(const value &from, const formats &fmts)
Deserialize a C++ value from from using the provided fmts.
@ 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.
Copyright (c) 2017-2026 by Travis Gockel.
Copyright (c) 2017-2026 by Travis Gockel.
Conversion between C++ types and JSON values.
JSONV_NO_RETURN JSONV_PUBLIC void deny_unknown_members(deserialization_context &context, const std::set< std::string > &unknown_members)
Throw a deserialization_error naming the unknown_members, the keys which claimed no member.
Represents a version used to deserialize and encode JSON objects from C++ classes.
Copyright (c) 2015-2026 by Travis Gockel.