568class formats_builder;
570template <
typename T>
class adapter_builder;
571template <
typename T,
typename TMember>
class member_adapter_builder;
572template <
typename TPo
inter>
class polymorphic_adapter_builder;
577class formats_builder_dsl
580 explicit formats_builder_dsl(formats_builder* owner) :
584 template <
typename T>
585 adapter_builder<T> type();
587 template <
typename T,
typename F>
588 adapter_builder<T> type(F&&);
590 template <
typename TEnum>
591 formats_builder& enum_type(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
593 template <
typename TEnum>
594 formats_builder& enum_type_icase(std::string enum_name, std::initializer_list<std::pair<TEnum, value>> mapping);
596 template <
typename TPo
inter>
597 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key =
"");
599 template <
typename TPo
inter,
typename F>
600 polymorphic_adapter_builder<TPointer> polymorphic_type(std::string discrimination_key, F&&);
602 template <
typename F>
603 formats_builder& extend(F&&);
605 formats_builder& register_adapter(
const adapter* p);
606 formats_builder& register_adapter(std::shared_ptr<const adapter> p);
608 formats_builder& reference_type(std::type_index typ);
609 formats_builder& reference_type(std::type_index type, std::type_index from);
611 template <
typename TOptional>
612 formats_builder& register_optional();
614 template <
typename TContainer>
615 formats_builder& register_container();
617 template <
typename T,
template <
class...>
class... TTContainers>
618 formats_builder& register_containers();
620 template <
typename TWrapper>
621 formats_builder& register_wrapper();
623 formats_builder& check_references(
const formats& other,
const std::string& name =
"");
624 formats_builder& check_references(
const formats::list& others,
const std::string& name =
"");
625 formats_builder& check_references(
const std::string& name =
"");
630 formats compose_checked(formats other,
const std::string& name =
"");
632 formats compose_checked(std::vector<formats> others,
const std::string& name =
"");
635 operator formats()
const;
638 formats_builder* owner;
642class adapter_builder_dsl
645 explicit adapter_builder_dsl(adapter_builder<T>* owner) :
649 adapter_builder<T>& type_default_on_null(
bool on =
true);
651 adapter_builder<T>& type_default_value(std::function<T (extraction_context& ctx)> create);
653 adapter_builder<T>& type_default_value(
const T& value);
655 template <
typename TMember>
656 member_adapter_builder<T, TMember> member(std::string name, TMember T::*selector);
658 template <
typename TMember>
659 member_adapter_builder<T, TMember> member(std::string name,
660 std::function<
const TMember& (
const T&)> access,
661 std::function<
void (T&, TMember&&)> mutate
664 template <
typename TMember>
665 member_adapter_builder<T, TMember> member(std::string name,
666 const TMember& (T::*access)() const,
667 TMember& (T::*mutable_access)()
670 template <
typename TMember>
671 member_adapter_builder<T, TMember> member(std::string name,
672 const TMember& (T::*access)() const,
673 void (T::*mutate)(TMember)
676 template <
typename TMember>
677 member_adapter_builder<T, TMember> member(std::string name,
678 const TMember& (T::*access)() const,
679 void (T::*mutate)(TMember&&)
682 adapter_builder<T>& pre_extract(
typename adapter_builder<T>::pre_extract_func perform);
684 adapter_builder<T>& post_extract(
typename adapter_builder<T>::post_extract_func perform);
686 adapter_builder<T>& on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler);
689 adapter_builder<T>* owner;
698inline bool current_is_null(
const reader& from)
700 if (
const value* lent = from.current_value())
701 return lent->kind() == jsonv::kind::null;
703 return from.good() && from.current().type() == ast_node_type::literal_null;
707constexpr std::size_t no_extract_key = std::size_t(-1);
720class member_claim_set
724 static constexpr std::uint16_t unclaimed = std::uint16_t(-1);
727 explicit member_claim_set(std::size_t count)
729 if (count > inline_capacity)
731 _spilled = std::make_unique<std::uint16_t[]>(count);
732 std::fill_n(_spilled.get(), count, unclaimed);
736 _ranks.fill(unclaimed);
742 std::uint16_t claim_rank(std::size_t idx)
const
744 return _spilled ? _spilled[idx] : _ranks[idx];
748 bool claimed(std::size_t idx)
const
750 return claim_rank(idx) != unclaimed;
754 void claim(std::size_t idx, std::size_t rank)
758 auto stored = std::uint16_t(std::min<std::size_t>(rank, unclaimed - 1U));
761 _spilled[idx] = stored;
763 _ranks[idx] = stored;
767 static constexpr std::size_t inline_capacity = 64U;
772 std::array<std::uint16_t, inline_capacity> _ranks;
773 std::unique_ptr<std::uint16_t[]> _spilled;
780 virtual ~member_adapter() noexcept
791 virtual std::expected<void, ast_node_type>
792 extract(extraction_context& context, reader& from, std::string_view key, T& out)
const = 0;
797 virtual std::expected<void, ast_node_type> apply_default(extraction_context& context, T& out)
const = 0;
799 virtual void to_json(
const serialization_context& context,
const T& from, value& out)
const = 0;
803 virtual bool has_default()
const = 0;
812 virtual std::size_t extract_key_rank(std::string_view key)
const = 0;
817 virtual std::string_view primary_name()
const = 0;
820template <
typename T,
typename TMember>
821class member_adapter_impl :
822 public member_adapter<T>
825 using mutator_type = std::function<void (T&, TMember&&)>;
826 using accessor_type = std::function<
const TMember& (
const T&)>;
829 explicit member_adapter_impl(std::string name, mutator_type mutator, accessor_type access) :
830 _names({ std::move(name) }),
831 _set_value(std::move(mutator)),
832 _get_value(std::move(access))
835 explicit member_adapter_impl(std::string name, TMember T::*selector) :
836 member_adapter_impl(
std::move(name),
837 [selector] (T& value, TMember&& x) { value.*selector = std::move(x); },
838 [selector] (
const T& value) ->
const TMember& {
return value.*selector; }
843 virtual std::expected<void, ast_node_type>
844 extract(extraction_context& context, reader& from, std::string_view key, T& out)
const override
846 if (_default_on_null && current_is_null(from))
848 (void) from.next_token();
849 return apply_default(context, out);
859 auto extracted = [&] () -> std::expected<TMember, ast_node_type>
861 extraction_context::path_scope scope(context, key);
863 return context.extract<TMember>(from);
867 return std::unexpected(extracted.error());
872 _set_value(out, _extract_mutate(*std::move(extracted)));
874 _set_value(out, *std::move(extracted));
880 virtual std::expected<void, ast_node_type> apply_default(extraction_context& context, T& out)
const override
882 _set_value(out, _default_value(context));
886 virtual void to_json(
const serialization_context& context,
const T& from, value& out)
const override
888 if (should_encode(context, from))
889 out.
insert({ _names.at(0), context.to_json(_get_value(from)) });
893 virtual bool has_default()
const override
895 return bool(_default_value);
899 virtual std::size_t extract_key_rank(std::string_view key)
const override
901 for (std::size_t rank = 0U; rank < _names.size(); ++rank)
902 if (_names[rank] == key)
905 return no_extract_key;
909 virtual std::string_view primary_name()
const override
914 void add_encode_check(std::function<
bool (
const serialization_context&,
const TMember&)>
check)
918 auto old_check = std::move(_should_encode);
919 _should_encode = [
check, old_check] (
const serialization_context& context,
const TMember& value)
921 return check(context, value) && old_check(context, value);
926 _should_encode = std::move(
check);
930 void add_extraction_mutator(std::function <TMember (TMember&&)> mutate)
934 auto old_mutate = std::move(_extract_mutate);
935 _extract_mutate = [old_mutate, mutate] (TMember&& member) {
return mutate(old_mutate(std::move(member))); };
939 _extract_mutate = std::move(mutate);
943 void add_extraction_check(std::function <
void (
const TMember&)>
check)
945 add_extraction_mutator([
check] (TMember&& value)
952 void default_value(std::function<TMember (extraction_context&)>&& create)
954 _default_value = std::move(create);
957 void default_on_null(
bool on)
959 _default_on_null = on;
963 bool should_encode(
const serialization_context& context,
const T& from)
const
966 return _should_encode(context, _get_value(from));
975 template <
typename U,
typename UMember>
979 std::vector<std::string> _names;
980 mutator_type _set_value;
981 accessor_type _get_value;
982 std::function<bool (
const serialization_context&,
const TMember&)> _should_encode;
983 std::function<TMember (extraction_context&)> _default_value;
984 bool _default_on_null =
false;
985 std::function<TMember (TMember&&)> _extract_mutate;
990template <
typename T,
typename TMember>
992 public detail::formats_builder_dsl,
993 public detail::adapter_builder_dsl<T>
998 detail::member_adapter_impl<T, TMember>*
adapter
1004 reference_type(std::type_index(
typeid(
TMember)), std::type_index(
typeid(T)));
1010 _adapter->_names.emplace_back(std::move(
name));
1016 _adapter->add_extraction_check(std::move(
check));
1020 member_adapter_builder& check_input(std::function<
bool (
const TMember&)>
check,
1021 std::function<
void (
const TMember&)> thrower
1024 _adapter->add_extraction_check([
check, thrower] (
const TMember& value)
1032 template <
typename TException>
1033 member_adapter_builder& check_input(std::function<
void (
const TMember&)>
check,
const TException& ex)
1035 return check_input(std::move(
check), [ex] (
const TMember&) {
throw ex; });
1043 _adapter->default_value(std::move(create));
1058 _adapter->default_on_null(
on);
1067 _adapter->add_encode_check(std::move(
check));
1116 detail::member_adapter_impl<T, TMember>* _adapter;
1119template <
typename T>
1121 public detail::formats_builder_dsl
1129 template <
typename F>
1131 formats_builder_dsl(owner),
1134 auto adapter = std::make_shared<adapter_impl>();
1138 std::forward<F>(
f)(*this);
1147 _adapter->_default_on_null =
on;
1153 _adapter->_create_default = std::move(create);
1162 template <
typename TMember>
1165 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
1167 new detail::member_adapter_impl<T, TMember>(std::move(
name),
selector)
1170 _adapter->_members.emplace_back(std::move(ptr));
1174 template <
typename TMember>
1180 std::unique_ptr<detail::member_adapter_impl<T, TMember>> ptr
1182 new detail::member_adapter_impl<T, TMember>(std::move(
name), std::move(
mutate), std::move(
access))
1185 _adapter->_members.emplace_back(std::move(ptr));
1189 template <
typename TMember>
1201 template <
typename TMember>
1213 template <
typename TMember>
1227 if (_adapter->_pre_extract)
1229 pre_extract_func
old_perform = std::move(_adapter->_pre_extract);
1238 _adapter->_pre_extract = std::move(
perform);
1245 if (_adapter->_post_extract)
1247 post_extract_func
old_perform = std::move(_adapter->_post_extract);
1255 _adapter->_post_extract = std::move(
perform);
1266 if (_adapter->_extra_keys)
1268 extra_keys_func
old_handler = std::move(_adapter->_extra_keys);
1277 _adapter->_extra_keys = std::move(
handler);
1283 class adapter_impl :
1288 _default_on_null(
false)
1292 virtual std::expected<T, ast_node_type> create(extraction_context& context, reader& from)
const override
1295 _pre_extract(context);
1297 if (_default_on_null && detail::current_is_null(from))
1299 (void) from.next_token();
1303 return _create_default(context);
1310 context.note_value_consumed(from);
1315 auto opened = context.current_as<ast_node::object_begin>(from);
1317 return std::unexpected(opened.error());
1320 detail::member_claim_set claims(_members.size());
1321 bool recovered =
false;
1322 bool closed =
false;
1327 std::optional<std::set<std::string>> extra_keys;
1328 std::optional<std::set<std::string>> repeated_keys;
1335 repeated_keys.emplace();
1340 (void) from.next_token();
1346 auto type = from.current().type();
1348 if (type == ast_node_type::document_end || type == ast_node_type::error)
1352 return context.problem(context.problem_path(from),
"Unterminated object");
1354 else if (type == ast_node_type::object_end)
1367 std::optional<std::string> decoded;
1368 std::string_view key;
1369 if (type == ast_node_type::key_canonical)
1371 key = from.current().as<ast_node::key_canonical>().value();
1373 else if (type == ast_node_type::key_escaped)
1375 key = decoded.emplace(from.current().as<ast_node::key_escaped>().value());
1379 auto matched = context.expect(from,
1380 { ast_node_type::key_canonical, ast_node_type::key_escaped }
1382 return std::unexpected(matched.error());
1385 if (!from.next_token())
1386 return context.problem(context.problem_path(from),
"Unterminated object");
1388 if (repeated_keys && !repeated_keys->emplace(key).second)
1393 std::string message(
"Duplicate key in object: \"");
1394 message.append(key);
1395 message.append(
"\"");
1397 (void) context.problem(context.path(), std::move(message));
1399 if (!context.recover())
1400 return std::unexpected(ast_node_type::error);
1403 (void) from.next_value();
1407 auto matched = find_member(key);
1408 if (matched.index == _members.size())
1415 extra_keys.emplace();
1417 extra_keys->emplace(key);
1420 (void) from.next_value();
1424 if (
auto held = claims.claim_rank(matched.index); held != detail::member_claim_set::unclaimed)
1426 if (matched.rank > held)
1432 (void) from.next_value();
1435 else if (matched.rank == held && !consume_duplicate(context, from))
1444 const auto& member = *_members[matched.index];
1445 auto walked = run_member(context,
1448 [&] {
return member.
extract(context, from, key, out); }
1452 claims.claim(matched.index, matched.rank);
1455 return std::unexpected(walked.error());
1461 return context.problem(context.problem_path(from),
"Unterminated object");
1465 if (_extra_keys && extra_keys && !extra_keys->empty())
1466 _extra_keys(context, *std::move(extra_keys));
1468 for (std::size_t idx = 0U; idx < _members.size(); ++idx)
1470 if (claims.claimed(idx))
1473 const auto& member = *_members[idx];
1474 if (!member.has_default())
1476 std::string message(
"Missing required field ");
1477 message.append(member.primary_name());
1479 (void) context.problem(context.path(), std::move(message));
1480 if (!context.recover())
1481 return std::unexpected(ast_node_type::error);
1489 auto applied = run_member(context,
1492 [&] {
return member.apply_default(context, out); }
1496 return std::unexpected(applied.error());
1508 walk_to_close(from);
1516 return std::unexpected(ast_node_type::error);
1519 out = _post_extract(context, std::move(out));
1522 (void) from.next_token();
1532 context.note_value_consumed(from);
1537 virtual value
to_json(
const serialization_context& context,
const T& from)
const override
1540 for (
const auto& member : _members)
1541 member->
to_json(context, from, out);
1546 std::deque<std::unique_ptr<detail::member_adapter<T>>> _members;
1547 pre_extract_func _pre_extract;
1548 post_extract_func _post_extract;
1549 extra_keys_func _extra_keys;
1550 std::function<T (extraction_context&)> _create_default;
1551 bool _default_on_null;
1569 member_match find_member(std::string_view key)
const
1571 for (std::size_t idx = 0U; idx < _members.size(); ++idx)
1572 if (
auto rank = _members[idx]->extract_key_rank(key); rank != detail::no_extract_key)
1573 return member_match{ idx, rank };
1575 return member_match{ _members.size(), detail::no_extract_key };
1588 static bool consume_duplicate(extraction_context& context, reader& from)
1592 (void) from.next_value();
1611 template <
typename FRun>
1613 static std::expected<bool, ast_node_type> run_member(extraction_context& context,
1614 const detail::member_adapter<T>& member,
1621 if (
auto result = run())
1625 else if (!context.recover())
1627 return std::unexpected(result.error());
1631 context.skip_failed_value(*from);
1634 catch (
const extraction_error& ex)
1638 if (!context.recover(ex))
1641 catch (
const std::bad_alloc&)
1660 extraction_context::path_scope scope(context, member.primary_name());
1661 extraction_error translated(context.path(), std::current_exception());
1663 if (!context.recover(translated))
1674 static void walk_to_close(reader& from)
noexcept
1678 auto type = from.current().type();
1679 if ( type == ast_node_type::object_end
1680 || type == ast_node_type::document_end
1681 || type == ast_node_type::error
1686 else if (type == ast_node_type::key_canonical || type == ast_node_type::key_escaped)
1689 (void) from.next_key();
1693 (void) from.next_value();
1700 adapter_impl* _adapter;
1703template <
typename TPo
inter>
1705 public detail::formats_builder_dsl
1708 template <
typename F>
1713 formats_builder_dsl(owner),
1717 auto adapter = std::make_shared<polymorphic_adapter<TPointer>>();
1721 std::forward<F>(
f)(*this);
1733 _adapter->check_null_input(
on);
1739 _adapter->check_null_output(
on);
1743 template <
typename TSub>
1747 if (_discrimination_key.empty())
1748 throw std::logic_error(
"Cannot use single-argument subtype if no discrimination_key has been set");
1753 template <
typename TSub>
1761 reference_type(std::type_index(
typeid(
TSub)), std::type_index(
typeid(
TPointer)));
1765 template <
typename TSub>
1769 reference_type(std::type_index(
typeid(
TSub)), std::type_index(
typeid(
TPointer)));
1773 template <
typename TSub>
1785 std::string _discrimination_key;
1793 template <
typename T>
1799 template <
typename T,
typename F>
1805 template <
typename TEnum>
1807 std::initializer_list<std::pair<TEnum, value>>
mapping
1813 template <
typename TEnum>
1815 std::initializer_list<std::pair<TEnum, value>>
mapping
1821 template <
typename TPo
inter>
1828 template <
typename TPo
inter,
typename F>
1835 template <
typename F>
1838 std::forward<F>(
func)(*this);
1844 _formats.register_adapter(
p, _duplicate_type_action);
1850 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1854 template <
typename TOptional>
1857 reference_type(std::type_index(
typeid(
typename TOptional::value_type)), std::type_index(
typeid(
TOptional)));
1859 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1863 template <
typename TContainer>
1866 reference_type(std::type_index(
typeid(
typename TContainer::value_type)), std::type_index(
typeid(
TContainer)));
1868 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1872 template <
typename TWrapper>
1875 reference_type(std::type_index(
typeid(
typename TWrapper::value_type)), std::type_index(
typeid(
TWrapper)));
1877 _formats.register_adapter(std::move(
p), _duplicate_type_action);
1881 template <
typename T>
1887 template <
typename T,
template <
class...>
class TTContainer,
template <
class...>
class...
TTRest>
1891 return register_containers<T,
TTRest...>();
1924 formats compose_checked(
const formats::list&
others,
const std::string&
name =
"");
1938 std::map<std::type_index, std::set<std::type_index>> _referenced_types;
1944template <
typename T>
1947 return owner->type<T>();
1950template <
typename T,
typename F>
1951adapter_builder<T> formats_builder_dsl::type(F&& f)
1953 return owner->type<T>(std::forward<F>(f));
1956template <
typename TEnum>
1957formats_builder& formats_builder_dsl::enum_type(std::string enum_name,
1958 std::initializer_list<std::pair<TEnum, value>> mapping
1961 return owner->enum_type<TEnum>(std::move(enum_name), mapping);
1964template <
typename TEnum>
1965formats_builder& formats_builder_dsl::enum_type_icase(std::string enum_name,
1966 std::initializer_list<std::pair<TEnum, value>> mapping
1969 return owner->enum_type_icase<TEnum>(std::move(enum_name), mapping);
1972template <
typename TPo
inter>
1973polymorphic_adapter_builder<TPointer>
1974formats_builder_dsl::polymorphic_type(std::string discrimination_key)
1976 return owner->polymorphic_type<TPointer>(std::move(discrimination_key));
1979template <
typename TPo
inter,
typename F>
1980polymorphic_adapter_builder<TPointer>
1981formats_builder_dsl::polymorphic_type(std::string discrimination_key, F&& f)
1983 return owner->polymorphic_type<TPointer>(std::move(discrimination_key), std::forward<F>(f));
1986template <
typename F>
1987formats_builder& formats_builder_dsl::extend(F&& f)
1989 return owner->extend(std::forward<F>(f));
1992template <
typename TOptional>
1993formats_builder& formats_builder_dsl::register_optional()
1995 return owner->register_optional<TOptional>();
1998template <
typename TContainer>
1999formats_builder& formats_builder_dsl::register_container()
2001 return owner->register_container<TContainer>();
2004template <
typename T,
template <
class...>
class... TTContainers>
2005formats_builder& formats_builder_dsl::register_containers()
2007 return owner->register_containers<T, TTContainers...>();
2010template <
typename TWrapper>
2011formats_builder& formats_builder_dsl::register_wrapper()
2013 return owner->register_container<TWrapper>();
2016template <
typename T>
2017adapter_builder<T>& adapter_builder_dsl<T>::type_default_on_null(
bool on)
2019 return owner->type_default_on_null(on);
2022template <
typename T>
2023adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(std::function<T (extraction_context& ctx)> create)
2025 return owner->type_default_value(std::move(create));
2028template <
typename T>
2029adapter_builder<T>& adapter_builder_dsl<T>::type_default_value(
const T& value)
2031 return owner->type_default_value(value);
2034template <
typename T>
2035template <
typename TMember>
2036member_adapter_builder<T, TMember> adapter_builder_dsl<T>::member(std::string name, TMember T::*selector)
2038 return owner->member(std::move(name), selector);
2041template <
typename T>
2042template <
typename TMember>
2043member_adapter_builder<T, TMember>
2044adapter_builder_dsl<T>::member(std::string name,
2045 std::function<
const TMember& (
const T&)> access,
2046 std::function<
void (T&, TMember&&)> mutate
2049 return owner->member(std::move(name), std::move(access), std::move(mutate));
2052template <
typename T>
2053template <
typename TMember>
2054member_adapter_builder<T, TMember>
2055adapter_builder_dsl<T>::member(std::string name,
2056 const TMember& (T::*access)() const,
2057 TMember& (T::*mutable_access)()
2060 return owner->member(std::move(name), access, mutable_access);
2063template <
typename T>
2064template <
typename TMember>
2065member_adapter_builder<T, TMember>
2066adapter_builder_dsl<T>::member(std::string name,
2067 const TMember& (T::*access)() const,
2068 void (T::*mutate)(TMember)
2071 return owner->member(std::move(name), access, mutate);
2074template <
typename T>
2075template <
typename TMember>
2076member_adapter_builder<T, TMember>
2077adapter_builder_dsl<T>::member(std::string name,
2078 const TMember& (T::*access)() const,
2079 void (T::*mutate)(TMember&&)
2082 return owner->member(std::move(name), access, mutate);
2085template <
typename T>
2086adapter_builder<T>& adapter_builder_dsl<T>::pre_extract(
typename adapter_builder<T>::pre_extract_func perform)
2088 return owner->pre_extract(std::move(perform));
2091template <
typename T>
2092adapter_builder<T>& adapter_builder_dsl<T>::post_extract(
typename adapter_builder<T>::post_extract_func perform)
2094 return owner->post_extract(std::move(perform));
2097template <
typename T>
2098adapter_builder<T>& adapter_builder_dsl<T>::on_extract_extra_keys(
typename adapter_builder<T>::extra_keys_func handler)
2100 return owner->on_extract_extra_keys(std::move(handler));
adapter_builder< T > & on_extract_extra_keys(extra_keys_func handler)
The handler is stored rather than desugared into a pre_extract, because the keys which claimed no mem...
An adapter for the type T.
virtual value to_json(const serialization_context &context, const void *from) const override
virtual std::expected< void, ast_node_type > extract(extraction_context &context, reader &from, void *into) const override
An adapter is both an extractor and a serializer.
Provides extra information to routines used for extraction and serialization.
const std::optional< jsonv::version > & version() const
Get the version this context was created with.
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 was not created with a version,...
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 & default_value(std::function< TMember(extraction_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 & after(version ver)
Only encode this member if the serialization_context was not created with a version,...
member_adapter_builder & before(version ver)
Only encode this member if the serialization_context was not created with a version,...
member_adapter_builder & until(version ver)
Only encode this member if the serialization_context was not created with a version,...
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_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.
Copyright (c) 2015-2026 by Travis Gockel.
Copyright (c) 2015 by Travis Gockel.
Copyright (c) 2015-2026 by Travis Gockel.
duplicate_type_action
The action to take when an insertion of an extractor or serializer into a formats is attempted,...
T extract(const value &from, const formats &fmts)
Extract a C++ value from from using the provided fmts.
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) 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 throw_extra_keys_extraction_error(extraction_context &context, const std::set< std::string > &extra_keys)
Throw an extraction_error naming the extra_keys which claimed no member.
Represents a version used to extract and encode JSON objects from C++ classes.
Copyright (c) 2015-2026 by Travis Gockel.