11#include <daw/daw_utility.h>
20 template<
typename OutputIterator>
21 inline constexpr OutputIterator output_kv( OutputIterator
it,
23 std::string_view value ) {
31 namespace json_details {
32 template<
typename JsonMember,
bool is_root =
false,
33 typename OutputIterator>
34 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Bool>,
35 OutputIterator out_it ) {
37 if constexpr( not is_root ) {
40 out_it.next_member( );
42 out_it = utils::output_kv( out_it, R
"("type")", R"("boolean")" );
43 if constexpr( not is_root ) {
46 out_it.next_member( );
47 if constexpr( not is_root ) {
53 template<
typename JsonMember,
bool is_root =
false,
54 typename OutputIterator>
55 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Custom>,
56 OutputIterator out_it ) {
59 static_assert( JsonMember::custom_json_type ==
61 if constexpr( not is_root ) {
64 out_it.next_member( );
66 out_it = utils::output_kv( out_it, R
"("type")", R"("string")" );
67 if constexpr( not is_root ) {
70 out_it.next_member( );
71 if constexpr( not is_root ) {
77 template<
typename JsonMember,
bool is_root =
false,
78 typename OutputIterator>
79 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Date>,
80 OutputIterator out_it ) {
82 if constexpr( not is_root ) {
85 out_it.next_member( );
87 out_it = utils::output_kv( out_it, R
"("type")", R"("string")" );
89 out_it.next_member( );
90 out_it = utils::output_kv( out_it, R
"("format")", R"("date-time")" );
91 if constexpr( not is_root ) {
94 out_it.next_member( );
95 if constexpr( not is_root ) {
101 template<
typename JsonMember,
bool is_root =
false,
102 typename OutputIterator>
103 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Real>,
104 OutputIterator out_it ) {
106 if constexpr( not is_root ) {
108 out_it.add_indent( );
109 out_it.next_member( );
111 out_it = utils::output_kv( out_it, R
"("type")", R"("number")" );
112 if constexpr( not is_root ) {
113 out_it.del_indent( );
115 out_it.next_member( );
116 if constexpr( not is_root ) {
122 template<
typename JsonMember,
bool is_root =
false,
123 typename OutputIterator>
124 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Signed>,
125 OutputIterator out_it ) {
127 if constexpr( not is_root ) {
129 out_it.add_indent( );
130 out_it.next_member( );
132 out_it = utils::output_kv( out_it, R
"("type")", R"("integer")" );
133 if constexpr( not is_root ) {
134 out_it.del_indent( );
136 out_it.next_member( );
137 if constexpr( not is_root ) {
143 template<
typename JsonMember,
bool is_root =
false,
144 typename OutputIterator>
145 constexpr OutputIterator
146 to_json_schema( ParseTag<JsonParseTypes::StringEscaped>,
147 OutputIterator out_it ) {
149 if constexpr( not is_root ) {
151 out_it.add_indent( );
152 out_it.next_member( );
154 out_it = utils::output_kv( out_it, R
"("type")", R"("string")" );
155 if constexpr( not is_root ) {
156 out_it.del_indent( );
158 out_it.next_member( );
159 if constexpr( not is_root ) {
165 template<
typename JsonMember,
bool is_root =
false,
166 typename OutputIterator>
167 constexpr OutputIterator
168 to_json_schema( ParseTag<JsonParseTypes::StringRaw>,
169 OutputIterator out_it ) {
171 if constexpr( not is_root ) {
173 out_it.add_indent( );
174 out_it.next_member( );
176 out_it = utils::output_kv( out_it, R
"("type")", R"("string")" );
177 if constexpr( not is_root ) {
178 out_it.del_indent( );
180 out_it.next_member( );
181 if constexpr( not is_root ) {
187 template<
typename JsonMember,
bool is_root =
false,
188 typename OutputIterator>
189 constexpr OutputIterator
190 to_json_schema( ParseTag<JsonParseTypes::Unsigned>,
191 OutputIterator out_it ) {
192 if constexpr( not is_root ) {
194 out_it.add_indent( );
195 out_it.next_member( );
197 out_it = utils::output_kv( out_it, R
"("type")", R"("integer")" );
199 out_it.next_member( );
200 out_it = utils::output_kv( out_it, R
"("minimum")", "0" );
201 if constexpr( not is_root ) {
202 out_it.del_indent( );
204 out_it.next_member( );
205 if constexpr( not is_root ) {
220 template<
typename JsonMember,
bool is_root =
false,
221 typename OutputIterator>
222 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Class>,
223 OutputIterator out_it );
234 template<
typename JsonMember,
bool is_root =
false,
235 typename OutputIterator>
236 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Array>,
237 OutputIterator out_it );
239 template<
typename JsonMember,
bool is_root =
false,
240 typename OutputIterator>
241 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Tuple>,
242 OutputIterator out_it );
244 template<
typename JsonMember,
bool is_root =
false,
245 typename OutputIterator>
246 constexpr OutputIterator
247 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
248 OutputIterator out_it );
250 template<
typename JsonMember,
bool is_root =
false,
251 typename OutputIterator>
252 constexpr OutputIterator
253 to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
254 OutputIterator out_it );
256 template<
typename JsonMember,
bool is_root =
false,
257 typename OutputIterator>
258 constexpr OutputIterator
259 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
260 OutputIterator out_it );
262 template<
typename JsonMember,
bool is_root =
false,
263 typename OutputIterator>
264 constexpr OutputIterator
265 to_json_schema( ParseTag<JsonParseTypes::Variant>,
266 OutputIterator out_it );
268 template<
typename JsonMember,
bool is_root =
false,
269 typename OutputIterator>
270 constexpr OutputIterator
271 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
272 OutputIterator out_it );
274 template<
typename JsonMember,
bool is_root =
false,
275 typename OutputIterator>
276 constexpr OutputIterator
277 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
278 OutputIterator out_it );
280 template<
typename,
typename>
281 struct json_class_processor;
287 template<
typename OutputIterator,
typename... JsonMembers>
288 struct json_class_processor<OutputIterator,
289 json_member_list<JsonMembers...>> {
291 static constexpr std::size_t size =
sizeof...( JsonMembers );
297 static constexpr OutputIterator process( OutputIterator out_it ) {
298 out_it = utils::output_kv( out_it, R
"("type")", R"("object")" );
300 out_it.next_member( );
301 out_it = utils::output_kv( out_it, R
"("properties")", "{" );
302 if constexpr(
sizeof...( JsonMembers ) > 0 ) {
303 out_it.add_indent( );
304 out_it.next_member( );
305 out_it = output_member_types(
306 out_it, std::index_sequence_for<JsonMembers...>{ } );
307 out_it.del_indent( );
308 out_it.next_member( );
312 out_it.next_member( );
313 out_it = utils::output_kv( out_it, R
"("required")", "[" );
315 out_it.add_indent( );
316 out_it = output_required_members( out_it );
317 out_it.del_indent( );
318 out_it.next_member( );
321 if constexpr( ( has_dependent_member_v<JsonMembers> or ... ) ) {
323 out_it.next_member( );
324 out_it = utils::output_kv( out_it, R
"("dependencies")", "{" );
325 out_it.add_indent( );
326 bool is_first =
true;
327 out_it =
static_cast<OutputIterator
>(
329 json_link_no_name<json_link_no_name<JsonMembers>>>(
332 out_it.del_indent( );
335 out_it.next_member( );
343 static constexpr auto indexer =
344 std::index_sequence_for<JsonMembers...>{ };
352 template<
typename JsonMember, std::
size_t Idx>
353 static constexpr OutputIterator
354 output_member_type( OutputIterator &out_it,
bool *seen ) {
364 out_it.output_space( );
365 out_it = to_json_schema<JsonMember>(
366 ParseTag<JsonMember::base_expected_type>{ }, out_it );
367 if constexpr( Idx + 1 <
sizeof...( JsonMembers ) ) {
369 out_it.next_member( );
374 template<std::size_t... Is>
375 static constexpr OutputIterator
376 output_member_types( OutputIterator &out_it,
377 std::index_sequence<Is...> ) {
378 bool seen[
sizeof...( JsonMembers )]{ };
379 return static_cast<OutputIterator
>(
380 ( output_member_type<JsonMembers, Is>( out_it, seen ), ... ) );
383 template<
typename JsonMember>
384 static constexpr OutputIterator
385 output_required_member( OutputIterator &out_it,
bool &is_first ) {
392 out_it.next_member( );
400 template<
typename JsonMember>
401 static constexpr OutputIterator
402 output_dependency( OutputIterator &out_it,
bool &is_first ) {
403 if constexpr( has_dependent_member_v<JsonMember> ) {
409 out_it.next_member( );
413 out_it.output_space( );
415 out_it.add_indent( );
416 out_it.next_member( );
419 out_it, dependent_member_t<JsonMember>::name );
421 out_it.del_indent( );
422 out_it.next_member( );
428 static constexpr OutputIterator
429 output_required_members( OutputIterator &out_it ) {
430 bool is_first =
true;
431 return ( output_required_member<json_link_no_name<JsonMembers>>(
437 template<
typename OutputIterator,
typename... JsonMembers>
438 struct json_class_processor<OutputIterator,
439 json_tuple_member_list<JsonMembers...>> {
441 static constexpr std::size_t size =
sizeof...( JsonMembers );
442 static constexpr OutputIterator process( OutputIterator out_it ) {
444 out_it = utils::output_kv( out_it, R
"("type")", R"("array",)" );
445 out_it.next_member( );
446 out_it = utils::output_kv( out_it, R"("items")", "[" );
447 if constexpr(
sizeof...( JsonMembers ) > 0 ) {
448 out_it.add_indent( );
449 out_it = output_member_types( out_it );
450 out_it.del_indent( );
451 out_it.next_member( );
456 not( ( json_link_no_name<JsonMembers>::base_expected_type ==
459 "A tagged variant is not supported in a tuple/ordered json "
464 static constexpr OutputIterator
465 output_member_types( OutputIterator &out_it ) {
466 bool is_first =
true;
467 return static_cast<OutputIterator
>(
468 ( output_member_type<json_link_no_name<JsonMembers>>( out_it,
473 template<
typename JsonMember>
474 static constexpr OutputIterator
475 output_member_type( OutputIterator &out_it,
bool &is_first ) {
481 out_it.next_member( );
482 out_it = to_json_schema<JsonMember>(
483 ParseTag<JsonMember::base_expected_type>{ }, out_it );
488 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
489 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Class>,
490 OutputIterator out_it ) {
491 using json_class_processor_t = json_class_processor<
493 json_data_contract_trait_t<typename JsonMember::base_type>>;
495 if constexpr( not is_root ) {
497 out_it.add_indent( );
499 if constexpr( json_class_processor_t::size > 0 ) {
500 out_it.next_member( );
501 out_it = json_class_processor_t::process( out_it );
503 if constexpr( not is_root ) {
504 out_it.del_indent( );
506 if constexpr( not is_root ) {
507 out_it.next_member( );
513 namespace json_details {
514 template<
typename Tuple,
bool is_root,
typename OutputIterator,
516 constexpr OutputIterator
517 to_json_tuple_schema( OutputIterator out_it,
518 std::index_sequence<Is...> ) {
519 if constexpr( not is_root ) {
521 out_it.add_indent( );
523 out_it.next_member( );
524 out_it = utils::output_kv( out_it, R
"("type")", R"("array",)" );
525 out_it.next_member( );
526 out_it = utils::output_kv( out_it, R"("items")", "[" );
527 if constexpr(
sizeof...( Is ) > 0 ) {
528 out_it.add_indent( );
529 bool is_first =
true;
530 auto const process_member = [&](
auto Idx ) {
536 out_it.next_member( );
537 static constexpr std::size_t index =
decltype( Idx )::value;
538 using pack_element = tuple_elements_pack<Tuple>;
540 typename pack_element::template element_t<index>>;
542 out_it = to_json_schema<JsonMember>(
543 ParseTag<JsonMember::base_expected_type>{ }, out_it );
546 daw::Empty expander[] = {
547 ( process_member( daw::constant<Is>{ } ), daw::Empty{ } )...,
550 out_it.del_indent( );
551 out_it.next_member( );
554 if constexpr( not is_root ) {
555 out_it.del_indent( );
557 out_it.next_member( );
558 if constexpr( not is_root ) {
565 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
566 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Tuple>,
567 OutputIterator out_it ) {
568 using tuple_t =
typename JsonMember::sub_member_list;
569 return json_details::to_json_tuple_schema<tuple_t, is_root>(
571 std::make_index_sequence<tuple_elements_pack<tuple_t>::size>{ } );
574 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
575 constexpr OutputIterator to_json_schema( ParseTag<JsonParseTypes::Array>,
576 OutputIterator out_it ) {
577 if constexpr( not is_root ) {
579 out_it.add_indent( );
581 out_it.next_member( );
582 out_it = utils::output_kv( out_it, R
"("type")", R"("array",)" );
583 out_it.next_member( );
585 out_it.output_space( );
586 using element_t =
typename JsonMember::json_element_t;
587 out_it = to_json_schema<element_t>(
588 ParseTag<element_t::base_expected_type>{ }, out_it );
589 if constexpr( not is_root ) {
590 out_it.del_indent( );
592 out_it.next_member( );
593 if constexpr( not is_root ) {
599 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
600 constexpr OutputIterator
601 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
602 OutputIterator out_it ) {
603 return to_json_schema<JsonMember, is_root>(
604 ParseTag<JsonParseTypes::Array>{ }, out_it );
607 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
608 constexpr OutputIterator
609 to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
610 OutputIterator out_it ) {
611 if constexpr( not is_root ) {
613 out_it.add_indent( );
615 out_it.next_member( );
616 out_it = utils::output_kv( out_it, R
"("type")", R"("object")" );
618 out_it.next_member( );
619 out_it = utils::output_kv( out_it, R
"("additionalProperties")", "" );
620 using element_t =
typename JsonMember::json_element_t;
621 out_it = to_json_schema<element_t>(
622 ParseTag<element_t::base_expected_type>{ }, out_it );
623 if constexpr( not is_root ) {
624 out_it.del_indent( );
626 out_it.next_member( );
627 if constexpr( not is_root ) {
633 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
634 constexpr OutputIterator
635 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
636 OutputIterator out_it ) {
637 if constexpr( not is_root ) {
639 out_it.add_indent( );
641 out_it.next_member( );
642 out_it = utils::output_kv( out_it, R
"("type")", R"("array",)" );
643 out_it.next_member( );
645 out_it.output_space( );
646 using element_t =
typename JsonMember::json_class_t;
647 out_it = to_json_schema<element_t>(
648 ParseTag<element_t::base_expected_type>{ }, out_it );
649 if constexpr( not is_root ) {
650 out_it.del_indent( );
652 out_it.next_member( );
653 if constexpr( not is_root ) {
659 template<
typename...>
660 struct variant_element_types;
662 template<
typename... JsonElements>
663 struct variant_element_types<json_variant_type_list<JsonElements...>> {
665 template<
typename JsonElement,
typename OutputIterator>
666 static constexpr OutputIterator output_element( OutputIterator out_it,
673 out_it.next_member( );
674 return to_json_schema<JsonElement>(
675 ParseTag<JsonElement::base_expected_type>{ }, out_it );
678 template<
typename OutputIterator>
679 static constexpr OutputIterator
680 output_elements( OutputIterator out_it ) {
681 bool is_first =
true;
682 return static_cast<OutputIterator
>(
683 ( output_element<JsonElements>( out_it, is_first ), ... ) );
687 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
688 constexpr OutputIterator
689 to_json_schema( ParseTag<JsonParseTypes::Variant>,
690 OutputIterator out_it ) {
691 if constexpr( not is_root ) {
693 out_it.add_indent( );
695 out_it.next_member( );
696 out_it = utils::output_kv( out_it, R
"("oneOf")", "[" );
697 using elements_t =
typename JsonMember::json_elements;
698 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
699 out_it.add_indent( );
700 out_it = variant_element_types<elements_t>::output_elements( out_it );
701 out_it.del_indent( );
702 out_it.next_member( );
705 if constexpr( not is_root ) {
706 out_it.del_indent( );
708 out_it.next_member( );
709 if constexpr( not is_root ) {
715 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
716 constexpr OutputIterator
717 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
718 OutputIterator out_it ) {
719 static_assert( not is_root,
720 "Attempt to have a tagged variant as root object. This "
723 out_it.add_indent( );
724 out_it.next_member( );
725 out_it = utils::output_kv( out_it, R
"("oneOf")", "[" );
726 using elements_t =
typename JsonMember::json_elements;
727 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
728 out_it.add_indent( );
729 out_it = variant_element_types<elements_t>::output_elements( out_it );
730 out_it.del_indent( );
731 out_it.next_member( );
734 out_it.del_indent( );
735 out_it.next_member( );
740 template<
typename JsonMember,
bool is_root,
typename OutputIterator>
741 constexpr OutputIterator
742 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
743 OutputIterator out_it ) {
744 if constexpr( not is_root ) {
746 out_it.add_indent( );
748 out_it.next_member( );
749 out_it = utils::output_kv( out_it, R
"("oneOf")", "[" );
750 using elements_t =
typename JsonMember::json_elements;
751 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
752 out_it.add_indent( );
753 out_it = variant_element_types<elements_t>::output_elements( out_it );
754 out_it.del_indent( );
755 out_it.next_member( );
758 if constexpr( not is_root ) {
759 out_it.del_indent( );
761 out_it.next_member( );
762 if constexpr( not is_root ) {
769 template<
typename T,
typename OutputIterator>
770 constexpr OutputIterator to_json_schema( OutputIterator
it,
772 std::string_view title ) {
775 std::conditional_t<is_serialization_policy<OutputIterator>::value,
777 serialization_policy<OutputIterator>>;
778 auto out_it = iter_t(
it );
780 out_it.add_indent( );
781 out_it.next_member( );
782 out_it = utils::output_kv(
783 out_it, R
"("$schema")",
784 R"("https://json-schema.org/draft/2020-12/schema",)" );
785 out_it.next_member( );
786 out_it = utils::output_kv( out_it, R"("$id")", "\"" );
789 out_it.next_member( );
790 out_it = utils::output_kv( out_it, R"("title")", "\"" );
793 using json_type = json_link_no_name<T>;
794 out_it = json_details::to_json_schema<json_type, true>(
795 ParseTag<json_type::base_expected_type>{ }, out_it );
796 out_it.del_indent( );
797 out_it.next_member( );
803 typename SerializationPolicy = use_default_serialization_policy,
804 typename Result = std::string>
805 Result to_json_schema( std::string_view
id, std::string_view title ) {
806 auto result = Result( );
807 using iter_t = std::back_insert_iterator<Result>;
808 using policy = std::conditional_t<
809 std::is_same_v<SerializationPolicy, use_default_serialization_policy>,
810 serialization_policy<iter_t>, SerializationPolicy>;
812 (void)to_json_schema<T>( policy( iter_t( result ) ), id, title );
Iterator & it
Definition: daw_json_traits.h:251
typename json_type_deducer< T, is_an_ordered_member_v< T >, has_json_data_contract_trait_v< T >, json_details::is_a_json_type_v< T >, has_json_link_quick_map_v< T >, is_container_v< T > >::type json_deduced_type
Definition: daw_json_parse_common.h:953
constexpr OutputIterator copy_to_iterator(OutputIterator it, Container const &container)
Definition: to_daw_json_string.h:391
@ Tuple
A variant type where the Switcher is based on a submember of the class being parsed.
@ VariantTagged
Any one of the basic json types class/array/boolean/number/string.
constexpr bool is_empty_pack_v
Definition: daw_json_traits.h:191
Definition: daw_from_json.h:22
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16