18 #include <daw/daw_array.h>
19 #include <daw/daw_bounded_string.h>
20 #include <daw/daw_parser_helper_sv.h>
21 #include <daw/daw_traits.h>
22 #include <daw/daw_utility.h>
23 #include <daw/daw_visit.h>
24 #include <daw/iterator/daw_back_inserter.h>
30 #include <string_view>
39 template<
typename... JsonMembers>
42 static_assert( ( json_details::is_a_json_type_v<JsonMembers> and ... ),
43 "Only JSON Link mapping types can appear in a "
44 "json_member_list(e.g. json_number, json_string...)" );
46 not( is_no_name<JsonMembers> or ... ),
47 "All members must have a name and not no_name in a json_member_list" );
58 template<
typename OutputIterator,
typename Value,
typename... Args>
59 [[maybe_unused, nodiscard]]
static inline constexpr OutputIterator
60 serialize( OutputIterator it, std::tuple<Args...>
const &args,
62 static_assert( json_details::CheckMatch<Value,
sizeof...( Args ),
63 sizeof...( JsonMembers )>::value,
64 "Argument count is incorrect" );
66 return json_details::serialize_json_class<JsonMembers...>(
67 it, std::index_sequence_for<Args...>{ }, args, v );
79 template<
typename T,
typename Range>
80 [[maybe_unused, nodiscard]]
static inline constexpr T
82 return json_details::parse_json_class<T, JsonMembers...>(
83 rng, std::index_sequence_for<JsonMembers...>{ } );
87 template<
typename... Members>
91 [[nodiscard, maybe_unused]]
static inline auto const &
103 template<std::
size_t Index,
typename JsonMember>
108 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
109 using parse_to_t =
typename json_details::unnamed_default_type_mapping<
113 namespace json_details {
114 template<
typename JsonMember>
115 struct ordered_member_wrapper
116 : json_details::unnamed_default_type_mapping<JsonMember> {};
130 template<
typename... JsonMembers>
143 template<
typename OutputIterator,
typename Value,
typename... Args>
144 [[maybe_unused, nodiscard]]
static inline constexpr OutputIterator
145 serialize( OutputIterator it, std::tuple<Args...>
const &args,
147 static_assert(
sizeof...( Args ) ==
sizeof...( JsonMembers ),
148 "Argument count is incorrect" );
150 static_assert( ( json_details::is_a_json_type_v<
151 json_details::ordered_member_wrapper<JsonMembers>> and
153 "Only value JSON types can be used" );
154 return json_details::serialize_ordered_json_class<
155 json_details::ordered_member_wrapper<JsonMembers>...>(
156 it, std::index_sequence_for<Args...>{ }, args, v );
168 template<
typename T,
typename Range>
169 [[maybe_unused, nodiscard]]
static inline constexpr T
171 return json_details::parse_ordered_json_class<
172 T, json_details::ordered_member_wrapper<JsonMembers>...>( rng );
187 template<
typename TagMember,
typename Switcher,
typename... JsonClasses>
198 template<
typename OutputIterator,
typename Value>
199 [[maybe_unused, nodiscard]]
static inline constexpr OutputIterator
202 return daw::visit_nt( v, [&](
auto const &alternative ) {
203 using Alternative = daw::remove_cvref_t<decltype( alternative )>;
204 static_assert( ( std::is_same_v<Alternative, JsonClasses> or ... ),
205 "Unexpected alternative type" );
206 static_assert( json_details::has_json_to_json_data_v<Alternative>,
207 "Alternative type does not have a to_json_data_member "
208 "in it's json_data_contract specialization" );
210 return json_details::member_to_string<json_class<no_name, Alternative>>(
224 template<
typename T,
typename Range>
225 [[maybe_unused, nodiscard]]
static inline constexpr T
228 std::size_t
const idx = [rng]( )
mutable {
229 return Switcher{ }( std::get<0>(
234 return json_details::parse_nth_class<0, T,
false,
260 using base_type = json_details::unwrap_type<T, Nullable>;
261 static_assert( not std::is_same_v<void, base_type>,
262 "Failed to detect base type" );
264 static_assert( daw::is_arithmetic_v<base_type>,
265 "json_number requires an arithmetic type" );
266 using parse_to_t = std::invoke_result_t<Constructor, base_type>;
268 Nullable == JsonNullable::Never or
269 std::is_same_v<
parse_to_t, std::invoke_result_t<Constructor>>,
270 "Default ctor of constructor must match that of base" );
272 static constexpr daw::string_view
name = Name;
275 get_parse_type_v<json_details::number_parse_type_v<base_type>,
Nullable>;
278 json_details::number_parse_type_v<base_type>;
283 JsonBaseParseTypes::Number;
299 using base_type = json_details::unwrap_type<T, Nullable>;
300 static_assert( not std::is_same_v<void, base_type>,
301 "Failed to detect base type" );
302 using parse_to_t = std::invoke_result_t<Constructor, base_type>;
306 get_parse_type_v<JsonParseTypes::Bool, Nullable>;
309 static constexpr daw::string_view
name = Name;
312 JsonBaseParseTypes::Bool;
331 template<
JSONNAMETYPE Name,
typename String,
typename Constructor,
338 using base_type = json_details::unwrap_type<String, Nullable>;
339 static_assert( not std::is_same_v<void, base_type>,
340 "Failed to detect base type" );
341 using parse_to_t = std::invoke_result_t<Constructor, base_type>;
343 static constexpr daw::string_view
name = Name;
345 get_parse_type_v<JsonParseTypes::StringRaw, Nullable>;
347 JsonParseTypes::StringRaw;
351 JsonBaseParseTypes::String;
368 template<
JSONNAMETYPE Name,
typename String,
typename Constructor,
375 using base_type = json_details::unwrap_type<String, Nullable>;
376 static_assert( not std::is_same_v<void, base_type>,
377 "Failed to detect base type" );
378 using parse_to_t = std::invoke_result_t<Constructor, base_type>;
380 static constexpr daw::string_view
name = Name;
382 get_parse_type_v<JsonParseTypes::StringEscaped, Nullable>;
384 JsonParseTypes::StringEscaped;
388 JsonBaseParseTypes::String;
399 template<
JSONNAMETYPE Name,
typename T,
typename Constructor,
405 using base_type = json_details::unwrap_type<T, Nullable>;
406 static_assert( not std::is_same_v<void, base_type>,
407 "Failed to detect base type" );
409 std::invoke_result_t<Constructor, char const *, std::size_t>;
411 static constexpr daw::string_view
name = Name;
413 get_parse_type_v<JsonParseTypes::Date, Nullable>;
416 JsonBaseParseTypes::String;
429 template<
JSONNAMETYPE Name,
typename T,
typename Constructor,
435 using base_type = json_details::unwrap_type<T, Nullable>;
436 static_assert( not std::is_same_v<void, base_type>,
437 "Failed to detect base type" );
439 static constexpr daw::string_view
name = Name;
441 get_parse_type_v<JsonParseTypes::Class, Nullable>;
444 JsonBaseParseTypes::Class;
453 template<
typename... JsonElements>
457 sizeof...( JsonElements ) <= 5U,
458 "There can be at most 5 items, one for each JsonBaseParseTypes" );
460 std::tuple<json_details::unnamed_default_type_mapping<JsonElements>...>;
462 json_details::find_json_element<JsonBaseParseTypes::Number>(
463 { json_details::unnamed_default_type_mapping<
464 JsonElements>::underlying_json_type... } ),
465 json_details::find_json_element<JsonBaseParseTypes::Bool>(
466 { json_details::unnamed_default_type_mapping<
467 JsonElements>::underlying_json_type... } ),
468 json_details::find_json_element<JsonBaseParseTypes::String>(
469 { json_details::unnamed_default_type_mapping<
470 JsonElements>::underlying_json_type... } ),
471 json_details::find_json_element<JsonBaseParseTypes::Class>(
472 { json_details::unnamed_default_type_mapping<
473 JsonElements>::underlying_json_type... } ),
474 json_details::find_json_element<JsonBaseParseTypes::Array>(
475 { json_details::unnamed_default_type_mapping<
476 JsonElements>::underlying_json_type... } ) };
488 template<
JSONNAMETYPE Name,
typename T,
typename JsonElements,
493 std::is_same_v<typename JsonElements::i_am_variant_type_list, void>,
494 "Expected a json_variant_type_list" );
497 using base_type = json_details::unwrap_type<T, Nullable>;
498 static_assert( not std::is_same_v<void, base_type>,
499 "Failed to detect base type" );
501 static constexpr daw::string_view
name = Name;
503 get_parse_type_v<JsonParseTypes::Variant, Nullable>;
505 JsonParseTypes::Variant;
527 template<
JSONNAMETYPE Name,
typename T,
typename TagMember,
typename Switcher,
533 std::is_same_v<
typename JsonElements::i_am_tagged_variant_type_list,
535 "Expected a json_member_list" );
537 static_assert( std::is_same_v<typename TagMember::i_am_a_json_type, void>,
538 "JSON member types must be passed as "
544 using base_type = json_details::unwrap_type<T, Nullable>;
545 static_assert( not std::is_same_v<void, base_type>,
546 "Failed to detect base type" );
548 static constexpr daw::string_view
name = Name;
550 get_parse_type_v<JsonParseTypes::VariantTagged, Nullable>;
552 JsonParseTypes::VariantTagged;
568 template<
JSONNAMETYPE Name,
typename T,
typename FromJsonConverter,
577 using base_type = json_details::unwrap_type<T, Nullable>;
578 static_assert( not std::is_same_v<void, base_type>,
579 "Failed to detect base type" );
581 std::invoke_result_t<FromJsonConverter, std::string_view>;
582 static_assert( std::is_invocable_v<FromJsonConverter, std::string_view>,
583 "FromConverter must be callable with a std::string_view" );
585 std::is_invocable_v<ToJsonConverter, parse_to_t> or
586 std::is_invocable_r_v<
char const *, ToJsonConverter,
char const *,
588 "ToConverter must be callable with T or T and and OutputIterator" );
589 static constexpr daw::string_view
name = Name;
591 get_parse_type_v<JsonParseTypes::Custom, Nullable>;
595 JsonBaseParseTypes::String;
599 namespace json_details {
600 template<
JSONNAMETYPE Name,
typename JsonElement,
typename Container,
602 struct json_array_detect {
603 using i_am_a_json_type = void;
604 using json_element_t =
605 json_details::unnamed_default_type_mapping<JsonElement>;
606 static_assert( not std::is_same_v<json_element_t, void>,
607 "Unknown JsonElement type." );
608 static_assert( json_details::is_a_json_type_v<json_element_t>,
609 "Error determining element type" );
610 using constructor_t = Constructor;
612 using base_type = json_details::unwrap_type<Container, Nullable>;
613 static_assert( not std::is_same_v<void, base_type>,
614 "Failed to detect base type" );
615 using parse_to_t = std::invoke_result_t<Constructor>;
616 static constexpr daw::string_view name = Name;
618 get_parse_type_v<JsonParseTypes::Array, Nullable>;
620 JsonParseTypes::Array;
622 static_assert( json_element_t::name ==
no_name,
623 "All elements of json_array must be have no_name" );
625 JsonBaseParseTypes::Array;
641 template<
JSONNAMETYPE Name,
typename JsonElement,
typename Container,
646 json_details::unnamed_default_type_mapping<JsonElement>;
647 static_assert( not std::is_same_v<json_element_t, void>,
648 "Unknown JsonElement type." );
649 static_assert( json_details::is_a_json_type_v<json_element_t>,
650 "Error determining element type" );
653 using base_type = json_details::unwrap_type<Container, Nullable>;
654 static_assert( not std::is_same_v<void, base_type>,
655 "Failed to detect base type" );
657 static constexpr daw::string_view
name = Name;
659 get_parse_type_v<JsonParseTypes::Array, Nullable>;
662 static_assert( json_element_t::name ==
no_name,
663 "All elements of json_array must be have no_name" );
665 JsonBaseParseTypes::Array;
683 template<
JSONNAMETYPE Name,
typename Container,
typename JsonValueType,
688 using base_type = json_details::unwrap_type<Container, Nullable>;
689 static_assert( not std::is_same_v<void, base_type>,
690 "Failed to detect base type" );
693 json_details::unnamed_default_type_mapping<JsonValueType>;
694 static_assert( not std::is_same_v<json_element_t, void>,
695 "Unknown JsonValueType type." );
696 static_assert( json_element_t::name ==
no_name,
697 "Value member name must be the default no_name" );
699 using json_key_t = json_details::unnamed_default_type_mapping<JsonKeyType>;
700 static_assert( not std::is_same_v<json_key_t, void>,
701 "Unknown JsonKeyType type." );
702 static_assert( json_key_t::name ==
no_name,
703 "Key member name must be the default no_name" );
705 static constexpr daw::string_view
name = Name;
707 get_parse_type_v<JsonParseTypes::KeyValue, Nullable>;
709 JsonParseTypes::KeyValue;
711 JsonBaseParseTypes::Class;
730 template<
JSONNAMETYPE Name,
typename Container,
typename JsonValueType,
735 using base_type = json_details::unwrap_type<Container, Nullable>;
736 static_assert( not std::is_same_v<void, base_type>,
737 "Failed to detect base type" );
739 using json_key_t = json_details::unnamed_default_type_mapping<
740 JsonKeyType, json_details::default_key_name>;
741 static_assert( not std::is_same_v<json_key_t, void>,
742 "Unknown JsonKeyType type." );
743 static_assert( daw::string_view( json_key_t::name ) !=
745 "Must supply a valid key member name" );
747 JsonValueType, json_details::default_value_name>;
751 static_assert( not std::is_same_v<json_value_t, void>,
752 "Unknown JsonValueType type." );
753 static_assert( daw::string_view( json_value_t::name ) !=
755 "Must supply a valid value member name" );
756 static_assert( daw::string_view( json_key_t::name ) !=
757 daw::string_view( json_value_t::name ),
758 "Key and Value member names cannot be the same" );
759 static constexpr daw::string_view
name = Name;
761 get_parse_type_v<JsonParseTypes::KeyValueArray, Nullable>;
763 JsonParseTypes::KeyValueArray;
765 JsonBaseParseTypes::Array;
791 typename Constructor = daw::construct_a_t<T>,
797 using base_type = json_details::unwrap_type<T, Nullable>;
798 static_assert( not std::is_same_v<void, base_type>,
799 "Failed to detect base type" );
802 std::invoke_result_t<Constructor, char const *, char const *>;
803 static constexpr daw::string_view
name = Name;
823 template<
typename JsonMember,
825 bool KnownBounds =
false>
826 [[maybe_unused, nodiscard]] constexpr
auto
828 daw_json_assert( not json_data.empty( ), ErrorReason::EmptyJSONDocument );
829 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
830 auto rng = ParsePolicy( json_data.data( ),
832 static_cast<ptrdiff_t
>( json_data.size( ) ) );
834 return json_details::parse_value<json_member, KnownBounds>(
847 template<
typename JsonMember,
849 bool KnownBounds =
false,
typename Allocator>
850 [[maybe_unused, nodiscard]] constexpr
auto
852 daw_json_assert( not json_data.empty( ), ErrorReason::EmptyJSONDocument );
853 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
854 static_assert( json_details::is_allocator_v<Allocator> );
855 char const *f = json_data.data( );
856 char const *l = f +
static_cast<ptrdiff_t
>( json_data.size( ) );
857 auto rng = ParsePolicy::with_allocator( f, l, alloc );
859 return json_details::parse_value<json_member, KnownBounds>(
874 template<
typename JsonMember,
876 bool KnownBounds =
false>
877 [[maybe_unused, nodiscard]] constexpr
auto
878 from_json( std::string_view json_data, std::string_view member_path ) {
879 daw_json_assert( not json_data.empty( ), ErrorReason::EmptyJSONDocument );
880 daw_json_assert( not member_path.empty( ), ErrorReason::EmptyJSONPath );
881 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
882 auto [is_found, rng] = json_details::find_range<ParsePolicy>(
883 json_data, { std::data( member_path ), std::size( member_path ) } );
884 if constexpr( json_member::expected_type == JsonParseTypes::Null ) {
886 return typename json_member::constructor_t{ }( );
891 return json_details::parse_value<json_member, KnownBounds>(
906 template<
typename JsonMember,
908 bool KnownBounds =
false,
typename Allocator>
909 [[maybe_unused, nodiscard]] constexpr
auto
912 static_assert( json_details::is_allocator_v<Allocator> );
913 daw_json_assert( not json_data.empty( ), ErrorReason::EmptyJSONDocument );
914 daw_json_assert( not member_path.empty( ), ErrorReason::EmptyJSONPath );
915 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
916 auto [is_found, rng] = json_details::find_range<ParsePolicy>(
917 json_data, { std::data( member_path ), std::size( member_path ) },
919 if constexpr( json_member::expected_type == JsonParseTypes::Null ) {
921 return typename json_member::constructor_t{ }( );
926 return json_details::parse_value<json_member, KnownBounds>(
930 template<
typename JsonMember,
932 bool KnownBounds =
false,
typename Range>
933 [[maybe_unused, nodiscard]]
inline constexpr
auto
935 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
937 auto rng = ParsePolicy( json_data.data( ),
939 static_cast<ptrdiff_t
>( json_data.size( ) ) );
941 return json_details::parse_value<json_member, KnownBounds>(
945 template<
typename JsonMember,
947 bool KnownBounds =
false,
typename Range>
948 [[maybe_unused, nodiscard]] constexpr
auto
950 using json_member = json_details::unnamed_default_type_mapping<JsonMember>;
952 auto [is_found, rng] = json_details::find_range<ParsePolicy>(
953 json_data, { std::data( member_path ), std::size( member_path ) } );
954 if constexpr( json_member::expected_type == JsonParseTypes::Null ) {
956 return typename json_member::constructor_t{ }( );
961 return json_details::parse_value<json_member, KnownBounds>(
973 template<
typename Value,
975 typename json_details::unnamed_default_type_mapping<Value>,
976 typename OutputIterator>
977 [[maybe_unused]] constexpr OutputIterator
to_json( Value
const &value,
978 OutputIterator out_it ) {
979 if constexpr( std::is_pointer_v<OutputIterator> ) {
983 out_it = json_details::member_to_string<JsonClass>( out_it, value );
997 template<
typename Result = std::string,
typename Value,
999 typename json_details::unnamed_default_type_mapping<Value>>
1000 [[maybe_unused, nodiscard]] constexpr Result
to_json( Value
const &value ) {
1002 to_json<Value, JsonClass>( value, daw::back_inserter( result ) );
1020 template<
typename JsonElement,
1021 typename Container =
1022 std::vector<
typename json_details::unnamed_default_type_mapping<
1023 JsonElement>::parse_to_t>,
1025 typename Constructor = daw::construct_a_t<Container>,
1026 bool KnownBounds =
false>
1027 [[maybe_unused, nodiscard]] constexpr Container
1029 std::string_view member_path =
"" ) {
1030 daw_json_assert( not json_data.empty( ), ErrorReason::EmptyJSONDocument );
1032 ErrorReason::EmptyJSONPath );
1033 using element_type =
1034 json_details::unnamed_default_type_mapping<JsonElement>;
1035 static_assert( not std::is_same_v<element_type, void>,
1036 "Unknown JsonElement type." );
1040 auto [is_found, rng] = json_details::find_range<ParsePolicy>(
1041 json_data, { member_path.data( ), member_path.size( ) } );
1043 if constexpr( parser_t::expected_type == JsonParseTypes::Null ) {
1044 if( not is_found ) {
1045 return typename parser_t::constructor_t{ }( );
1050 rng.trim_left_unchecked( );
1051 #if defined( _MSC_VER ) and not defined( __clang__ )
1054 ErrorReason::InvalidArrayStart, rng );
1056 using Range = daw::remove_cvref_t<decltype( rng )>;
1058 ErrorReason::InvalidArrayStart, rng );
1061 return json_details::parse_value<parser_t, KnownBounds>(
1065 namespace json_details {
1070 struct auto_detect_array_element {};
1082 template<
typename JsonElement = json_details::auto_detect_array_element,
1083 typename Container,
typename OutputIterator>
1084 [[maybe_unused]] constexpr OutputIterator
1087 daw::traits::is_container_like_v<daw::remove_cvref_t<Container>>,
1088 "Supplied container must support begin( )/end( )" );
1090 if constexpr( std::is_pointer_v<OutputIterator> ) {
1094 bool is_first =
true;
1095 for(
auto const &v : c ) {
1096 using v_type = daw::remove_cvref_t<decltype( v )>;
1097 constexpr
bool is_auto_detect_v =
1098 std::is_same_v<JsonElement, json_details::auto_detect_array_element>;
1100 std::conditional_t<is_auto_detect_v,
1101 json_details::unnamed_default_type_mapping<v_type>,
1107 "Unable to detect unnamed mapping" );
1108 static_assert( not std::is_same_v<JsonElement, JsonMember> );
1114 out_it = json_details::member_to_string<JsonMember>( out_it, v );
1129 template<
typename Result = std::string,
1130 typename JsonElement = json_details::auto_detect_array_element,
1134 daw::traits::is_container_like_v<daw::remove_cvref_t<Container>>,
1135 "Supplied container must support begin( )/end( )" );
1138 auto out_it = json_details::basic_appender<Result>( result );
1139 to_json_array<JsonElement>( c, out_it );
1145 #if not defined( DAW_JSON_DISABLE_JSON_STRING_LITERAL )