23 #include <daw/cpp_17.h>
24 #include <daw/daw_allocator_construct.h>
25 #include <daw/daw_arith_traits.h>
26 #include <daw/daw_cpp_feature_check.h>
27 #include <daw/daw_fwd_pack_apply.h>
28 #include <daw/daw_move.h>
29 #include <daw/daw_scope_guard.h>
30 #include <daw/daw_string_view.h>
31 #include <daw/daw_traits.h>
39 #include <string_view>
44 namespace json_details {
45 DAW_MAKE_REQ_TRAIT_TYPE( is_json_member_list_v,
46 T::i_am_a_json_member_list );
49 using ordered_member_subtype_test =
typename T::json_member;
52 using ordered_member_subtype_t =
53 typename daw::detected_or_t<T, ordered_member_subtype_test, T>;
55 template<
typename T,
typename Default>
56 inline constexpr
auto json_class_constructor =
57 json_class_constructor_t<T, Default>{ };
59 template<
typename Value,
typename Constructor,
typename ParseState,
61 DAW_ATTRIB_INLINE
static constexpr
auto
62 construct_value( ParseState &parse_state, Args &&...args ) {
65 if constexpr( ParseState::has_allocator ) {
66 auto alloc = parse_state.template get_allocator_for<Value>( );
67 return daw::try_alloc_construct<Value, Constructor>(
68 std::move( alloc ), DAW_FWD( args )... );
71 std::is_invocable_v<Constructor, Args...>,
72 "Unable to construct value with the supplied arguments" );
73 return Constructor{ }( DAW_FWD2( Args, args )... );
77 #if not defined( DAW_JSON_USE_GENERIC_LAMBDAS )
78 template<
typename Constructor>
79 struct construct_value_tp_invoke_t {
80 template<
typename... TArgs, std::size_t... Is>
81 DAW_ATTRIB_INLINE constexpr
auto
82 operator( )( fwd_pack<TArgs...> &&tp,
83 std::index_sequence<Is...> )
const {
84 return Constructor{ }( get<Is>( std::move( tp ) )... );
87 template<
typename... TArgs,
typename Allocator, std::size_t... Is>
88 DAW_ATTRIB_INLINE constexpr
auto
89 operator( )( fwd_pack<TArgs...> &&tp, Allocator &alloc,
90 std::index_sequence<Is...> )
const {
91 return Constructor{ }( get<Is>( std::move( tp ) )...,
95 template<
typename Alloc,
typename... TArgs, std::size_t... Is>
96 DAW_ATTRIB_INLINE constexpr
auto
97 operator( )( std::allocator_arg_t, Alloc &&alloc,
98 fwd_pack<TArgs...> &&tp,
99 std::index_sequence<Is...> )
const {
101 return Constructor{ }( std::allocator_arg, DAW_FWD( alloc ),
102 get<Is>( std::move( tp ) )... );
105 template<
typename Constructor>
106 inline constexpr
auto construct_value_tp_invoke =
107 construct_value_tp_invoke_t<Constructor>{ };
110 template<
typename Value,
typename Constructor,
typename ParseState,
112 DAW_ATTRIB_FLATINLINE
static inline constexpr
auto
113 construct_value_tp( ParseState &parse_state,
114 fwd_pack<Args...> &&tp_args ) {
116 #if defined( DAW_JSON_USE_GENERIC_LAMBDAS )
117 if constexpr( ParseState::has_allocator ) {
119 typename ParseState::template allocator_type_as<Value>;
120 auto alloc = parse_state.template get_allocator_for<Value>( );
121 if constexpr( std::is_invocable_v<Constructor, Args..., alloc_t> ) {
122 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
123 return Constructor{ }( get<Is>( std::move( tp_args ) )...,
124 std::move( alloc ) );
125 }( std::make_index_sequence<
sizeof...( Args )>{ } );
126 }
else if constexpr( std::is_invocable_v<Constructor,
127 std::allocator_arg_t,
128 alloc_t, Args...> ) {
129 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
130 return Constructor{ }( std::allocator_arg, std::move( alloc ),
131 get<Is>( std::move( tp_args ) )... );
132 }( std::make_index_sequence<
sizeof...( Args )>{ } );
135 std::is_invocable_v<Constructor, Args...>,
136 "Unable to construct value with the supplied arguments" );
137 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
138 return Constructor{ }( get<Is>( std::move( tp_args ) )... );
139 }( std::make_index_sequence<
sizeof...( Args )>{ } );
145 std::is_invocable_v<Constructor, Args...>,
146 "Unable to construct value with the supplied arguments" );
147 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
148 return Constructor{ }( get<Is>( std::move( tp_args ) )... );
149 }( std::make_index_sequence<
sizeof...( Args )>{ } );
152 if constexpr( ParseState::has_allocator ) {
154 typename ParseState::template allocator_type_as<Value>;
155 auto alloc = parse_state.template get_allocator_for<Value>( );
156 if constexpr( std::is_invocable_v<Constructor, Args..., alloc_t> ) {
157 return construct_value_tp_invoke<Constructor>(
158 std::move( tp_args ), std::move( alloc ),
159 std::index_sequence_for<Args...>{ } );
160 }
else if constexpr( std::is_invocable_v<Constructor,
161 std::allocator_arg_t,
162 alloc_t, Args...> ) {
163 return construct_value_tp_invoke<Constructor>(
164 std::allocator_arg, std::move( alloc ), std::move( tp_args ),
165 std::index_sequence_for<Args...>{ } );
168 std::is_invocable_v<Constructor, Args...>,
169 "Unable to construct value with the supplied arguments" );
170 return construct_value_tp_invoke<Constructor>(
171 std::move( tp_args ), std::index_sequence_for<Args...>{ } );
177 std::is_invocable_v<Constructor, Args...>,
178 "Unable to construct value with the supplied arguments" );
179 return construct_value_tp_invoke<Constructor>(
180 std::move( tp_args ), std::index_sequence_for<Args...>{ } );
186 inline constexpr
bool has_json_data_contract_trait_v =
187 not std::is_same_v<missing_json_data_contract_for_or_unknown_type<T>,
191 using has_json_data_contract_trait =
192 std::bool_constant<has_json_data_contract_trait_v<T>>;
195 has_json_to_json_data_v,
199 is_submember_tagged_variant_v,
203 using json_nullable_member_type_t =
typename T::member_type;
209 template<
json_options_t CurrentOptions,
auto option,
auto... options>
211 set_bits(
number_opts, CurrentOptions, option, options... );
213 template<
json_options_t CurrentOptions,
auto option,
auto... options>
215 set_bits(
bool_opts, CurrentOptions, option, options... );
217 template<
json_options_t CurrentOptions,
auto option,
auto... options>
219 set_bits(
string_opts, CurrentOptions, option, options... );
221 template<
json_options_t CurrentOptions,
auto option,
auto... options>
225 template<
json_options_t CurrentOptions,
auto option,
auto... options>
236 namespace json_base {
243 template<
typename T,
typename JsonMember = use_default,
245 typename Constructor = use_default>
249 namespace json_details {
251 inline constexpr
bool is_json_nullable_v =
false;
253 template<
typename T,
typename JsonMember,
JsonNullable NullableType,
254 typename Constructor>
255 inline constexpr
bool is_json_nullable_v<
260 struct json_empty_class {
261 static_assert( std::is_empty_v<T>,
"T is expected to empty" );
262 using i_am_a_json_type = void;
263 using i_am_a_deduced_empty_class = void;
264 using wrapped_type = T;
267 using parse_to_t = T;
269 static constexpr
JsonParseTypes expected_type = JsonParseTypes::Class;
272 JsonBaseParseTypes::Class;
276 inline constexpr
bool is_deduced_empty_class_v<
277 T, std::void_t<typename T::i_am_a_deduced_empty_class>> =
true;
280 struct json_ordered_class {
281 static_assert( can_convert_to_tuple_v<T>,
"T is expected to empty" );
282 using i_am_a_json_type = void;
283 using i_am_a_deduced_ordered_class = void;
284 using wrapped_type = T;
287 using parse_to_t = T;
289 static constexpr
JsonParseTypes expected_type = JsonParseTypes::Tuple;
292 JsonBaseParseTypes::Class;
296 namespace json_base {
298 template<
typename T,
typename Constructor = use_default>
301 template<
typename T,
JsonNullable NullableType = JsonNullable::Nullable,
302 typename Constructor = use_default>
307 template<
typename JsonElement,
typename Container = use_default,
308 typename Constructor = use_default>
311 template<
typename T,
typename FromJsonConverter = use_default,
312 typename ToJsonConverter = use_default,
316 template<
typename Variant,
typename JsonElements = use_default,
317 typename Constructor = use_default>
320 template<
typename T,
typename TagMember,
typename Switcher,
321 typename JsonElements = use_default,
322 typename Constructor = use_default>
326 typename Constructor = use_default>
331 typename Constructor = use_default>
334 NullableType, Constructor>;
337 typename Constructor = use_default>
342 typename Constructor = use_default>
345 NullableType, Constructor>;
348 typename Constructor = use_default>
353 typename Constructor = use_default>
356 NullableType, Constructor>;
358 template<
typename T,
typename Constructor = use_default>
362 typename Constructor = use_default>
367 typename Constructor = use_default>
370 NullableType, Constructor>;
372 template<
typename Container,
typename JsonValueType = use_default,
373 typename JsonKeyType = use_default,
374 typename Constructor = use_default>
377 template<
typename Container,
typename JsonValueType = use_default,
378 typename JsonKeyType = use_default,
379 typename Constructor = use_default>
382 template<
typename Container,
typename JsonValueType,
typename JsonKeyType,
384 typename Constructor = use_default>
388 JsonValueType, JsonKeyType>,
389 NullableType, Constructor>;
391 template<
typename Tuple,
typename JsonTupleTypesList = use_default,
392 typename Constructor = use_default>
395 template<
typename Tuple,
typename JsonTupleTypesList = use_default,
397 typename Constructor = use_default>
400 NullableType, Constructor>;
412 template<
typename T,
typename Constructor = use_default>
424 template<
typename T,
JsonNullable NullableType = JsonNullable::Nullable,
425 typename Constructor = use_default>
431 namespace json_details {
434 number_parse_type_impl_test( ) {
435 if constexpr( daw::is_floating_point_v<T> ) {
436 return JsonParseTypes::Real;
437 }
else if constexpr( daw::is_signed_v<T> ) {
438 return JsonParseTypes::Signed;
440 static_assert( daw::is_unsigned_v<T> );
441 return JsonParseTypes::Unsigned;
446 DAW_ATTRIB_INLINE DAW_CONSTEVAL
JsonParseTypes number_parse_type_test( ) {
447 if constexpr( std::is_enum_v<T> ) {
448 return number_parse_type_impl_test<std::underlying_type_t<T>>( );
450 return number_parse_type_impl_test<T>( );
456 number_parse_type_test<T>( );
458 template<
typename,
typename =
void>
459 struct json_deduced_type_map {
460 static constexpr
bool is_null =
false;
461 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Unknown;
463 static constexpr
bool type_map_found =
false;
466 template<
typename JsonType>
468 struct json_deduced_type_map<
470 static constexpr
bool is_null =
false;
471 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Unknown;
473 using type = JsonType;
474 static constexpr
bool type_map_found =
true;
479 struct json_deduced_type_map<
481 static constexpr
bool is_null =
false;
482 using type =
typename json_data_contract<T>::type;
483 static_assert( is_json_member_list_v<type>,
484 "Expected a JSON member list" );
485 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Unknown;
487 static constexpr
bool type_map_found =
true;
491 struct json_deduced_type_map<
daw::string_view> {
492 static constexpr
bool is_null =
false;
493 static constexpr
JsonParseTypes parse_type = JsonParseTypes::StringRaw;
495 static constexpr
bool type_map_found =
true;
499 struct json_deduced_type_map<
std::string_view> {
500 static constexpr
bool is_null =
false;
501 static constexpr
JsonParseTypes parse_type = JsonParseTypes::StringRaw;
503 static constexpr
bool type_map_found =
true;
507 struct json_deduced_type_map<
std::string> {
508 static constexpr
bool is_null =
false;
510 JsonParseTypes::StringEscaped;
512 static constexpr
bool type_map_found =
true;
516 struct json_deduced_type_map<bool> {
517 static constexpr
bool is_null =
false;
518 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Bool;
520 static constexpr
bool type_map_found =
true;
525 #if defined( _LIBCPP_VERSION )
527 struct json_deduced_type_map<
528 typename
std::vector<bool>::const_reference> {
530 static constexpr
bool is_null =
false;
531 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Bool;
533 static constexpr
bool type_map_found =
true;
537 template<
typename Integer>
539 not json_details::has_json_data_contract_trait_v<Integer> and
540 daw::is_integral_v<Integer> )
542 not json_details::has_json_data_contract_trait_v<Integer> and
543 daw::is_integral_v<Integer> )> {
544 static constexpr
bool is_null =
false;
546 daw::is_signed_v<Integer> ? JsonParseTypes::Signed
547 : JsonParseTypes::Unsigned;
549 static constexpr
bool type_map_found =
true;
552 template<
typename Enum>
554 not json_details::has_json_data_contract_trait_v<Enum> and
555 std::is_enum_v<Enum> )
557 not json_details::has_json_data_contract_trait_v<Enum> and
558 std::is_enum_v<Enum> )> {
559 static constexpr
bool is_null =
false;
561 daw::is_signed_v<std::underlying_type<Enum>>
562 ? JsonParseTypes::Signed
563 : JsonParseTypes::Unsigned;
565 static constexpr
bool type_map_found =
true;
568 template<
typename FloatingPo
int>
570 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
571 daw::is_floating_point_v<FloatingPoint> )
573 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
574 daw::is_floating_point_v<FloatingPoint> )> {
575 static constexpr
bool is_null =
false;
576 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Real;
578 static constexpr
bool type_map_found =
true;
581 template<
typename Tuple>
583 not json_details::has_json_data_contract_trait_v<Tuple> and
586 not json_details::has_json_data_contract_trait_v<Tuple> and
587 is_tuple_v<Tuple> )> {
588 static constexpr
bool is_null =
false;
589 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Tuple;
591 static constexpr
bool type_map_found =
true;
594 namespace container_detect {
596 using is_string_test =
597 decltype( (
void)( std::begin( std::declval<T &>( ) ) ),
598 (
void)( std::end( std::declval<T &>( ) ) ),
599 std::declval<typename T::value_type>( ) );
602 template<
typename String>
603 inline constexpr
bool is_string_v = std::is_convertible_v<
604 char, daw::detected_t<container_detect::is_string_test, String>>;
607 is_associative_container_v,
608 ( (
void)( std::begin( std::declval<T &>( ) ) ),
609 (
void)( std::end( std::declval<T &>( ) ) ),
610 (
void)( std::declval<typename T::value_type>( ) ),
611 (
void)( std::declval<typename T::key_type>( ) ),
612 (
void)( std::declval<typename T::mapped_type>( ) ) ) );
615 using is_associative_container =
616 std::bool_constant<is_associative_container_v<T>>;
618 template<
typename AssociativeContainer>
620 not has_json_data_contract_trait_v<AssociativeContainer> and
621 is_associative_container_v<AssociativeContainer> )
623 not has_json_data_contract_trait_v<AssociativeContainer> and
624 is_associative_container_v<AssociativeContainer> )> {
625 static constexpr
bool is_null =
false;
626 using key =
typename AssociativeContainer::key_type;
627 using value =
typename AssociativeContainer::mapped_type;
628 static constexpr
JsonParseTypes parse_type = JsonParseTypes::KeyValue;
630 static constexpr
bool type_map_found =
true;
634 inline constexpr
bool is_deduced_array_v =
635 not has_json_data_contract_trait_v<T> and
636 not is_associative_container_v<T> and concepts::is_container_v<T> and
639 template<
typename Container>
641 struct json_deduced_type_map<
643 static constexpr
bool is_null =
false;
644 using value =
typename Container::value_type;
645 static constexpr
JsonParseTypes parse_type = JsonParseTypes::Array;
647 static constexpr
bool type_map_found =
true;
651 inline constexpr
bool has_nullable_type_map_v =
652 concepts::is_nullable_value_v<T> and
653 not has_json_data_contract_trait_v<T> and
654 daw::is_detected_v<json_deduced_type_map,
655 concepts::nullable_value_type_t<T>>;
659 struct json_deduced_type_map<
661 static constexpr
bool is_null =
true;
662 using sub_type = concepts::nullable_value_type_t<T>;
663 using type = json_deduced_type_map<sub_type>;
665 static constexpr
bool type_map_found =
true;
669 inline constexpr
bool has_deduced_type_mapping_v =
670 json_deduced_type_map<T>::type_map_found;
672 template<
typename... Ts>
673 inline constexpr
bool are_deduced_type_mapped_v =
674 ( has_deduced_type_mapping_v<Ts> and ... );
676 template<
typename Mapped,
bool Found = true>
677 struct json_link_quick_map_type {
678 static constexpr
bool value = Found;
679 using mapped_type = Mapped;
682 template<JsonParseTypes Value>
683 inline constexpr
bool is_arithmetic_parse_type_v =
684 daw::traits::equal_to_any_of_v<Value, JsonParseTypes::Signed,
685 JsonParseTypes::Unsigned,
686 JsonParseTypes::Real>;
689 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_link_quick_map( ) noexcept {
690 if constexpr( is_a_json_type_v<T> ) {
691 return json_link_quick_map_type<T>{ };
692 }
else if constexpr( has_deduced_type_mapping_v<T> ) {
693 using mapped_type_t = json_deduced_type_map<T>;
694 using parse_type = daw::constant<mapped_type_t::parse_type>;
695 using is_null = daw::constant<mapped_type_t::is_null>;
696 if constexpr( parse_type::value == JsonParseTypes::Unknown ) {
697 if constexpr( is_null::value ) {
698 if constexpr( has_json_data_contract_trait_v<
699 typename mapped_type_t::sub_type> ) {
700 return json_link_quick_map_type<
701 json_base::json_class_null<T>>{ };
703 return json_link_quick_map_type<json_base::json_raw_null<T>>{ };
706 return json_link_quick_map_type<json_base::json_raw<T>>{ };
708 }
else if constexpr( parse_type::value ==
709 JsonParseTypes::StringRaw ) {
710 if constexpr( is_null::value ) {
711 return json_link_quick_map_type<
712 json_base::json_string_raw_null<T>>{ };
714 return json_link_quick_map_type<json_base::json_string_raw<T>>{ };
716 }
else if constexpr( parse_type::value ==
717 JsonParseTypes::StringEscaped ) {
718 if constexpr( is_null::value ) {
719 return json_link_quick_map_type<
720 json_base::json_string_null<T>>{ };
722 return json_link_quick_map_type<json_base::json_string<T>>{ };
724 }
else if constexpr( parse_type::value == JsonParseTypes::Bool ) {
725 if constexpr( is_null::value ) {
726 return json_link_quick_map_type<json_base::json_bool_null<T>>{ };
728 return json_link_quick_map_type<json_base::json_bool<T>>{ };
730 }
else if constexpr( is_arithmetic_parse_type_v<parse_type::value> ) {
731 if constexpr( is_null::value ) {
732 return json_link_quick_map_type<
733 json_base::json_number_null<T>>{ };
735 return json_link_quick_map_type<json_base::json_number<T>>{ };
737 }
else if constexpr( parse_type::value == JsonParseTypes::Tuple ) {
738 if constexpr( is_null::value ) {
739 return json_link_quick_map_type<json_base::json_tuple_null<T>>{ };
741 return json_link_quick_map_type<json_base::json_tuple<T>>{ };
743 }
else if constexpr( parse_type::value == JsonParseTypes::KeyValue ) {
744 if constexpr( is_null::value ) {
745 using b_t = json_base_type_t<mapped_type_t>;
746 using k_t =
typename b_t::key;
747 using v_t =
typename b_t::value;
748 return json_link_quick_map_type<
749 json_base::json_key_value_null<T, v_t, k_t>>{ };
751 using k_t =
typename mapped_type_t::key;
752 using v_t =
typename mapped_type_t::value;
753 return json_link_quick_map_type<
754 json_base::json_key_value<T, v_t, k_t>>{ };
756 }
else if constexpr( parse_type::value == JsonParseTypes::Array ) {
757 if constexpr( is_null::value ) {
758 using b_t = json_base_type_t<mapped_type_t>;
759 using v_t =
typename b_t::value;
760 return json_link_quick_map_type<
761 json_base::json_nullable<T, json_base::json_array<v_t, T>>>{ };
763 using v_t =
typename mapped_type_t::value;
764 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
767 return json_link_quick_map_type<void, false>{ };
770 return json_link_quick_map_type<void, false>{ };
776 inline constexpr
bool has_json_link_quick_map_v =
777 decltype( json_link_quick_map<T>( ) )::value;
781 using json_link_quick_map_t =
782 typename decltype( json_link_quick_map<T>( ) )::mapped_type;
784 template<
typename JsonType>
785 struct json_class_map_type {
786 using type =
typename json_data_contract_trait_t<JsonType>::json_member;
790 struct is_json_class_map : std::false_type {};
793 inline constexpr
bool is_json_class_map_v =
794 has_json_data_contract_trait_v<T> and
795 is_json_class_map_v<json_data_contract_trait_t<T>>;
798 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( ) noexcept {
799 if constexpr( is_a_basic_json_value<T> ) {
800 return daw::traits::identity<json_base::json_raw<T>>{ };
801 }
else if constexpr( is_an_ordered_member_v<T> ) {
803 return daw::traits::identity<type>{ };
804 }
else if constexpr( has_json_data_contract_trait_v<T> ) {
805 static_assert( not std::is_same_v<T, void> );
807 using type = json_base::json_class<T>;
809 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
810 "Detection failure" );
811 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
812 "Detection failure" );
813 return daw::traits::identity<type>{ };
814 }
else if constexpr( has_json_link_quick_map_v<T> ) {
815 static_assert( not std::is_same_v<T, void> );
816 using type = json_link_quick_map_t<T>;
817 using rcvref_type = remove_cvref_t<type>;
818 static_assert( not std::is_same_v<rcvref_type, void>,
819 "Detection failure" );
820 static_assert( not is_nonesuch_v<rcvref_type>,
"Detection failure" );
821 return daw::traits::identity<type>{ };
822 }
else if constexpr( is_a_json_type_v<T> ) {
823 static_assert( not std::is_same_v<T, void> );
825 typename daw::conditional_t<is_json_class_map_v<T>,
826 json_class_map_type<T>,
827 daw::traits::identity<T>>::type;
828 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
829 "Detection failure" );
830 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
831 "Detection failure" );
832 return daw::traits::identity<type>{ };
833 }
else if constexpr( concepts::is_nullable_value_v<T> ) {
834 using value_type = concepts::nullable_value_type_t<T>;
836 typename decltype( json_deduced_type_impl<value_type>( ) )::type;
837 using type = json_base::json_nullable<T, sub_type>;
838 return daw::traits::identity<type>{ };
839 }
else if constexpr( concepts::is_container_v<T> ) {
840 using type = json_base::json_array<typename T::value_type, T>;
841 return daw::traits::identity<type>{ };
842 }
else if constexpr( std::is_empty_v<T> and
843 std::is_default_constructible_v<T> ) {
845 using type = json_details::json_empty_class<T>;
846 return daw::traits::identity<type>{ };
847 }
else if constexpr( can_convert_to_tuple_v<T> ) {
848 using type = json_base::json_tuple<T>;
849 return daw::traits::identity<type>{ };
851 static_assert( daw::deduced_false_v<T>,
852 "Could not deduced data contract type" );
857 using json_deduced_type =
858 typename DAW_TYPEOF( json_deduced_type_impl<T>( ) )::type;
861 inline constexpr
bool has_json_deduced_type_v =
862 not std::is_same_v<json_deduced_type<T>,
863 missing_json_data_contract_for_or_unknown_type<T>>;
865 template<
typename... Ts>
866 inline constexpr
bool all_have_deduced_type_v =
867 ( has_json_deduced_type_v<Ts> and ... );
869 template<
typename JsonElement,
typename Container,
typename Constructor>
870 struct json_constructor<
871 json_base::json_array<JsonElement, Container, Constructor>> {
872 using json_element_t = json_deduced_type<JsonElement>;
873 using json_element_parse_to_t = json_result_t<json_element_t>;
876 daw::conditional_t<std::is_same_v<Container, use_default>,
877 std::vector<json_element_parse_to_t>, Container>;
880 daw::conditional_t<std::is_same_v<use_default, Constructor>,
881 default_constructor<container_t>, Constructor>;
884 std::is_invocable_v<type, json_element_parse_to_t
const *,
885 json_element_parse_to_t
const *>,
886 "Constructor must support copy and/or move construction" );
889 template<
typename JsonElement,
typename Container,
typename Constructor>
891 json_base::json_array<JsonElement, Container, Constructor>> {
892 using constructor_t =
typename json_constructor<
893 json_base::json_array<JsonElement, Container, Constructor>>::type;
894 using json_element_t = json_deduced_type<JsonElement>;
895 using json_element_parse_to_t =
896 typename json_result<json_element_t>::type;
898 std::invoke_result_t<constructor_t, json_element_parse_to_t
const *,
899 json_element_parse_to_t
const *>;
903 inline constexpr
bool has_unnamed_default_type_mapping_v =
904 has_json_deduced_type_v<T>;
906 template<
typename JsonMember>
907 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
909 template<
typename Constructor,
typename... Members>
910 using json_class_parse_result_impl2 =
911 std::invoke_result_t<Constructor, json_result_t<Members>...>;
913 template<
typename Constructor,
typename... Members>
914 using json_class_parse_result_impl =
915 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
917 template<
typename Constructor,
typename... Members>
918 struct could_not_construct_from_members_error;
920 template<
typename Constructor,
typename... Members>
921 using json_class_parse_result_t =
typename daw::conditional_t<
922 std::is_invocable_v<Constructor, json_result_t<Members>...>,
923 std::invoke_result<Constructor, json_result_t<Members>...>,
924 daw::traits::identity<could_not_construct_from_members_error<
925 Constructor, Members...>>>::type;
927 template<
typename JsonMember>
928 using dependent_member_t =
typename JsonMember::dependent_member;
930 template<
typename JsonMember,
typename =
void>
931 inline constexpr
bool has_dependent_member_v =
false;
933 template<
typename JsonMember>
934 inline constexpr
bool has_dependent_member_v<
935 JsonMember, std::void_t<dependent_member_t<JsonMember>>> =
true;
938 T::member_type::dependent_member );
940 template<
typename JsonMember>
942 inline constexpr
bool has_dependent_member_v<
944 has_nullable_dependent_member_v<JsonMember>;
946 template<
typename Constructor>
947 [[nodiscard]] DAW_ATTRIB_INLINE constexpr
auto
948 construct_nullable_empty( ) {
949 if constexpr( std::is_invocable_v<
951 concepts::construct_nullable_with_empty_t> ) {
954 return Constructor{ }( );
#define DAW_JSON_MAKE_REQ_TRAIT(Name,...)
Disable concepts on gcc < 13.3. See https://github.com/beached/daw_json_link/issues/454.
#define DAW_JSON_ENABLEIF_S(...)
typename json_data_contract< T >::type json_data_contract_trait_t
This trait gets us the mapping type from the contract.
JsonParseTypes
The tags used by the parser to determine what parser to call.
@ Tuple
A variant type where the Switcher is based on a submember of the class being parsed.
JsonNullable
Control how json_nullable members are serialized.
JsonBaseParseTypes
The fundamental JSON types.
std::uint32_t json_options_t
DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT(ignore_unknown_members_v, json_data_contract< T >::ignore_unknown_members)
constexpr json_options_t string_opts_def
constexpr json_options_t number_opts_def
constexpr auto string_opts
constexpr json_options_t json_custom_opts_def
constexpr auto string_raw_opts
constexpr auto json_custom_opts
constexpr json_options_t string_raw_opts_def
constexpr auto number_opts
constexpr json_options_t bool_opts_def
constexpr auto construct_nullable_with_empty
Customization point traits.
DAW_JSON_REQUIRES(boost::describe::has_describe_members< T >::value and use_boost_describe_v< T >) struct json_data_contract< T >
Mapping class for JSON data structures to C++. It must be specialized in order to parse to a user cla...
Default Constructor for a type. It accounts for aggregate types and uses brace construction for them.
Mark a member as nullable.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.