DAW JSON Link
Loading...
Searching...
No Matches
daw_json_schema.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
12
17
18#include <daw/daw_utility.h>
19
20#include <cstddef>
21#include <string_view>
22#include <type_traits>
23
24namespace daw::json {
25 inline namespace DAW_JSON_VER {
26 namespace utils {
27 template<typename WriteableType>
28 static constexpr WriteableType output_kv( WriteableType it,
29 std::string_view key,
30 std::string_view value ) {
31 it.write( key, ":", it.space, value );
32 return it;
33 }
34 } // namespace utils
35 namespace json_details {
36 template<typename JsonMember, bool is_root = false,
37 typename WriteableType>
38 constexpr WriteableType to_json_schema( ParseTag<JsonParseTypes::Bool>,
39 WriteableType out_it ) {
40
41 if constexpr( not is_root ) {
42 out_it.put( '{' );
43 out_it.add_indent( );
44 out_it.next_member( );
45 }
46 out_it = utils::output_kv( out_it, R"("type")", R"("boolean")" );
47 if constexpr( not is_root ) {
48 out_it.del_indent( );
49 }
50 out_it.next_member( );
51 if constexpr( not is_root ) {
52 out_it.put( '}' );
53 }
54 return out_it;
55 }
56
57 template<typename JsonMember, bool is_root = false,
58 typename WriteableType>
59 constexpr WriteableType to_json_schema( ParseTag<JsonParseTypes::Custom>,
60 WriteableType out_it ) {
61 // TODO allow a trait to describe the valid literal types or if it
62 // matches one of the other predefined types
63 static_assert( JsonMember::custom_json_type ==
64 options::JsonCustomTypes::String );
65 if constexpr( not is_root ) {
66 out_it.put( '{' );
67 out_it.add_indent( );
68 out_it.next_member( );
69 }
70 out_it = utils::output_kv( out_it, R"("type")", R"("string")" );
71 if constexpr( not is_root ) {
72 out_it.del_indent( );
73 }
74 out_it.next_member( );
75 if constexpr( not is_root ) {
76 out_it.put( '}' );
77 }
78 return out_it;
79 }
80
81 template<typename JsonMember, bool is_root = false,
82 typename WriteableType>
83 constexpr WriteableType to_json_schema( ParseTag<JsonParseTypes::Date>,
84 WriteableType out_it ) {
85
86 if constexpr( not is_root ) {
87 out_it.put( '{' );
88 out_it.add_indent( );
89 out_it.next_member( );
90 }
91 out_it = utils::output_kv( out_it, R"("type")", R"("string")" );
92 out_it.put( ',' );
93 out_it.next_member( );
94 out_it = utils::output_kv( out_it, R"("format")", R"("date-time")" );
95 if constexpr( not is_root ) {
96 out_it.del_indent( );
97 }
98 out_it.next_member( );
99 if constexpr( not is_root ) {
100 out_it.put( '}' );
101 }
102 return out_it;
103 }
104
105 template<typename JsonMember, bool is_root = false,
106 typename WriteableType>
107 constexpr WriteableType to_json_schema( ParseTag<JsonParseTypes::Real>,
108 WriteableType out_it ) {
109
110 if constexpr( not is_root ) {
111 out_it.put( '{' );
112 out_it.add_indent( );
113 out_it.next_member( );
114 }
115 out_it = utils::output_kv( out_it, R"("type")", R"("number")" );
116 if constexpr( not is_root ) {
117 out_it.del_indent( );
118 }
119 out_it.next_member( );
120 if constexpr( not is_root ) {
121 out_it.put( '}' );
122 }
123 return out_it;
124 }
125
126 template<typename JsonMember, bool is_root = false,
127 typename WriteableType>
128 constexpr WriteableType to_json_schema( ParseTag<JsonParseTypes::Signed>,
129 WriteableType out_it ) {
130
131 if constexpr( not is_root ) {
132 out_it.put( '{' );
133 out_it.add_indent( );
134 out_it.next_member( );
135 }
136 out_it = utils::output_kv( out_it, R"("type")", R"("integer")" );
137 if constexpr( not is_root ) {
138 out_it.del_indent( );
139 }
140 out_it.next_member( );
141 if constexpr( not is_root ) {
142 out_it.put( '}' );
143 }
144 return out_it;
145 }
146
147 template<typename JsonMember, bool is_root = false, typename WritableType>
148 constexpr WritableType
149 to_json_schema( ParseTag<JsonParseTypes::StringEscaped>,
150 WritableType out_it ) {
151
152 if constexpr( not is_root ) {
153 out_it.put( '{' );
154 out_it.add_indent( );
155 out_it.next_member( );
156 }
157 out_it = utils::output_kv( out_it, R"("type")", R"("string")" );
158 if constexpr( not is_root ) {
159 out_it.del_indent( );
160 }
161 out_it.next_member( );
162 if constexpr( not is_root ) {
163 out_it.put( '}' );
164 }
165 return out_it;
166 }
167
168 template<typename JsonMember, bool is_root = false, typename WritableType>
169 constexpr WritableType
170 to_json_schema( ParseTag<JsonParseTypes::StringInsitu>,
171 WritableType out_it ) {
172 return to_json_schema<JsonMember, is_root>(
173 ParseTag<JsonParseTypes::StringEscaped>{ }, out_it );
174 }
175
176 template<typename JsonMember, bool is_root = false, typename WritableType>
177 constexpr WritableType
178 to_json_schema( ParseTag<JsonParseTypes::StringRaw>,
179 WritableType out_it ) {
180
181 if constexpr( not is_root ) {
182 out_it.put( '{' );
183 out_it.add_indent( );
184 out_it.next_member( );
185 }
186 out_it = utils::output_kv( out_it, R"("type")", R"("string")" );
187 if constexpr( not is_root ) {
188 out_it.del_indent( );
189 }
190 out_it.next_member( );
191 if constexpr( not is_root ) {
192 out_it.put( '}' );
193 }
194 return out_it;
195 }
196
197 template<typename JsonMember, bool is_root = false, typename WritableType>
198 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Unsigned>,
199 WritableType out_it ) {
200 if constexpr( not is_root ) {
201 out_it.put( '{' );
202 out_it.add_indent( );
203 out_it.next_member( );
204 }
205 out_it = utils::output_kv( out_it, R"("type")", R"("integer")" );
206 out_it.put( ',' );
207 out_it.next_member( );
208 out_it = utils::output_kv( out_it, R"("minimum")", "0" );
209 if constexpr( not is_root ) {
210 out_it.del_indent( );
211 }
212 out_it.next_member( );
213 if constexpr( not is_root ) {
214 out_it.put( '}' );
215 }
216 return out_it;
217 }
218
219 /***
220 * Output the schema of a json_class and it's members
221 * @tparam JsonMember A json_class type
222 * @tparam is_root Is this the root item in the schema.
223 * @tparam WritableType An iterator type that allows for assigning to
224 * the result of operator* and pre/post-fix incrementing
225 * @param out_it Current WritableType
226 * @return the last value of out_it
227 */
228 template<typename JsonMember, bool is_root = false, typename WritableType>
229 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Class>,
230 WritableType out_it );
231
232 /***
233 * Output the schema of a json_array and it's element type
234 * @tparam JsonMember A json_array type
235 * @tparam is_root Is this the root item in the schema.
236 * @tparam WritableType An iterator type that allows for assigning to
237 * the result of operator and pre/post-fix incrementing
238 * @param out_it Current WritableType
239 * @return the last value of out_it
240 */
241 template<typename JsonMember, bool is_root = false, typename WritableType>
242 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Array>,
243 WritableType out_it );
244
245 template<typename JsonMember, bool is_root = false, typename WritableType>
246 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Null>,
247 WritableType out_it );
248
249 template<typename JsonMember, bool is_root = false, typename WritableType>
250 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Tuple>,
251 WritableType out_it );
252
253 template<typename JsonMember, bool is_root = false, typename WritableType>
254 constexpr WritableType
255 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
256 WritableType out_it );
257
258 template<typename JsonMember, bool is_root = false, typename WritableType>
259 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
260 WritableType out_it );
261
262 template<typename JsonMember, bool is_root = false, typename WritableType>
263 constexpr WritableType
264 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
265 WritableType out_it );
266
267 template<typename JsonMember, bool is_root = false, typename WritableType>
268 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Variant>,
269 WritableType out_it );
270
271 template<typename JsonMember, bool is_root = false, typename WritableType>
272 constexpr WritableType
273 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
274 WritableType out_it );
275
276 template<typename JsonMember, bool is_root = false, typename WritableType>
277 constexpr WritableType
278 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
279 WritableType out_it );
280
281 template<typename, typename>
282 struct json_class_processor;
283
288 template<typename WritableType, typename... JsonMembers>
289 struct json_class_processor<WritableType,
290 json_member_list<JsonMembers...>> {
291
292 static constexpr std::size_t size = sizeof...( JsonMembers );
293
298 static constexpr WritableType process( WritableType out_it ) {
299 out_it = utils::output_kv( out_it, R"("type")", R"("object")" );
300 out_it.put( ',' );
301 out_it.next_member( );
302 out_it = utils::output_kv( out_it, R"("properties")", "{" );
303 if constexpr( sizeof...( JsonMembers ) > 0 ) {
304 out_it.add_indent( );
305 out_it.next_member( );
306 out_it = output_member_types(
307 out_it, std::index_sequence_for<JsonMembers...>{ } );
308 out_it.del_indent( );
309 out_it.next_member( );
310 }
311 out_it.put( '}' );
312 out_it.put( ',' );
313 out_it.next_member( );
314 out_it = utils::output_kv( out_it, R"("required")", "[" );
315 if constexpr( not is_empty_pack_v<JsonMembers...> ) {
316 out_it.add_indent( );
317 out_it = output_required_members( out_it );
318 out_it.del_indent( );
319 out_it.next_member( );
320 }
321 out_it.put( ']' );
322 if constexpr( ( has_dependent_member_v<JsonMembers> or ... ) ) {
323 out_it.put( ',' );
324 out_it.next_member( );
325 out_it = utils::output_kv( out_it, R"("dependencies")", "{" );
326 out_it.add_indent( );
327 bool is_first = true;
328 out_it = static_cast<WritableType>(
329 ( output_dependency<
330 json_link_no_name<json_link_no_name<JsonMembers>>>(
331 out_it, is_first ),
332 ... ) );
333 out_it.del_indent( );
334 if( not is_first ) {
335 // If we have at least 1 dependent member, is_first will be false
336 out_it.next_member( );
337 }
338 out_it.put( '}' );
339 }
340 return out_it;
341 }
342
343 private:
344 static constexpr auto indexer =
345 std::index_sequence_for<JsonMembers...>{ };
346
353 template<typename JsonMember, std::size_t Idx>
354 static constexpr WritableType output_member_type( WritableType &out_it,
355 bool *seen ) {
356 if( seen[Idx] ) {
357 return out_it;
358 } else {
359 seen[Idx] = true;
360 }
361
362 out_it.write(
363 '"', encode_member_name_v<JsonMember>, "\":", out_it.space );
364 out_it = to_json_schema<JsonMember>(
365 ParseTag<JsonMember::expected_type>{ }, out_it );
366 if constexpr( Idx + 1 < sizeof...( JsonMembers ) ) {
367 out_it.put( ',' );
368 out_it.next_member( );
369 }
370 return out_it;
371 }
372
373 template<std::size_t... Is>
374 DAW_ATTRIB_INLINE static constexpr WritableType
375 output_member_types( WritableType &out_it,
376 std::index_sequence<Is...> ) {
377 bool seen[sizeof...( JsonMembers )]{ };
378 return static_cast<WritableType>(
379 ( output_member_type<JsonMembers, Is>( out_it, seen ), ... ) );
380 }
381
382 template<typename JsonMember>
383 static constexpr WritableType
384 output_required_member( WritableType &out_it, bool &is_first ) {
385 if constexpr( not is_json_nullable_v<JsonMember> ) {
386 if( not is_first ) {
387 out_it.put( ',' );
388 } else {
389 is_first = false;
390 }
391 out_it.next_member( );
392 out_it.write( '"', encode_member_name_v<JsonMember>, '"' );
393 }
394 return out_it;
395 }
396
397 template<typename JsonMember>
398 static constexpr WritableType output_dependency( WritableType &out_it,
399 bool &is_first ) {
400 if constexpr( has_dependent_member_v<JsonMember> ) {
401 if( not is_first ) {
402 out_it.put( ',' );
403 } else {
404 is_first = false;
405 }
406 out_it.next_member( );
407 out_it.write(
408 '"', encode_member_name_v<JsonMember>, "\":", out_it.space, "[" );
409 out_it.add_indent( );
410 out_it.next_member( );
411 out_it.write(
412 '"', encode_member_name_v<dependent_member_t<JsonMember>>, '"' );
413 out_it.del_indent( );
414 out_it.next_member( );
415 out_it.put( ']' );
416 }
417 return out_it;
418 }
419
420 static constexpr WritableType
421 output_required_members( WritableType &out_it ) {
422 bool is_first = true;
423 return ( output_required_member<json_link_no_name<JsonMembers>>(
424 out_it, is_first ),
425 ... );
426 }
427 };
428
429 template<typename WritableType, typename... JsonMembers>
430 struct json_class_processor<WritableType,
431 json_tuple_member_list<JsonMembers...>> {
432
433 static constexpr std::size_t size = sizeof...( JsonMembers );
434 static constexpr WritableType process( WritableType out_it ) {
435
436 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
437 out_it.next_member( );
438 out_it = utils::output_kv( out_it, R"("items")", "[" );
439 if constexpr( sizeof...( JsonMembers ) > 0 ) {
440 out_it.add_indent( );
441 out_it = output_member_types( out_it );
442 out_it.del_indent( );
443 out_it.next_member( );
444 }
445 out_it.put( ']' );
446
447 static_assert(
448 not( ( json_link_no_name<JsonMembers>::expected_type ==
449 JsonParseTypes::VariantTagged ) or
450 ... ),
451 "A tagged variant is not supported in a tuple/ordered json "
452 "class" );
453 return out_it;
454 }
455
456 static constexpr WritableType
457 output_member_types( WritableType &out_it ) {
458 bool is_first = true;
459 return static_cast<WritableType>(
460 ( output_member_type<json_link_no_name<JsonMembers>>( out_it,
461 is_first ),
462 ... ) );
463 }
464
465 template<typename JsonMember>
466 static constexpr WritableType output_member_type( WritableType &out_it,
467 bool &is_first ) {
468 if( not is_first ) {
469 out_it.put( ',' );
470 } else {
471 is_first = false;
472 }
473 out_it.next_member( );
474 out_it = to_json_schema<JsonMember>(
475 ParseTag<JsonMember::expected_type>{ }, out_it );
476 return out_it;
477 }
478 };
479
480 template<typename JsonMember, bool is_root, typename WritableType>
481 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Class>,
482 WritableType out_it ) {
483 using json_class_processor_t = json_class_processor<
484 WritableType,
485 json_data_contract_trait_t<json_base_type_t<JsonMember>>>;
486
487 if constexpr( not is_root ) {
488 out_it.put( '{' );
489 out_it.add_indent( );
490 }
491 if constexpr( json_class_processor_t::size > 0 ) {
492 out_it.next_member( );
493 out_it = json_class_processor_t::process( out_it );
494 }
495 if constexpr( not is_root ) {
496 out_it.del_indent( );
497 }
498 if constexpr( not is_root ) {
499 out_it.next_member( );
500 out_it.put( '}' );
501 }
502 return out_it;
503 }
504
505 namespace json_details {
506 template<typename Tuple, bool is_root, typename WritableType,
507 std::size_t... Is>
508 DAW_ATTRIB_INLINE constexpr WritableType
509 to_json_tuple_schema( WritableType out_it,
510 std::index_sequence<Is...> ) {
511 if constexpr( not is_root ) {
512 out_it.put( '{' );
513 out_it.add_indent( );
514 }
515 out_it.next_member( );
516 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
517 out_it.next_member( );
518 out_it = utils::output_kv( out_it, R"("items")", "[" );
519 if constexpr( sizeof...( Is ) > 0 ) {
520 out_it.add_indent( );
521 bool is_first = true;
522 auto const process_member = [&is_first, &out_it]( auto Idx ) {
523 if( not is_first ) {
524 out_it.put( ',' );
525 } else {
526 is_first = false;
527 }
528 out_it.next_member( );
529 using index = daw::constant<DAW_TYPEOF( Idx )::value>;
530 using pack_element = tuple_elements_pack<Tuple>;
531 using JsonMember = json_deduced_type<
532 typename pack_element::template element_t<index::value>>;
533
534 out_it = to_json_schema<JsonMember>(
535 ParseTag<JsonMember::expected_type>{ }, out_it );
536 };
537
538 daw::empty_t expander[] = {
539 ( process_member( daw::constant_v<Is> ), daw::empty_t{ } )...,
540 daw::empty_t{ } };
541 (void)expander;
542 out_it.del_indent( );
543 out_it.next_member( );
544 }
545 out_it.put( ']' );
546 if constexpr( not is_root ) {
547 out_it.del_indent( );
548 }
549 out_it.next_member( );
550 if constexpr( not is_root ) {
551 out_it.put( '}' );
552 }
553 return out_it;
554 }
555 } // namespace json_details
556
557 template<typename JsonMember, bool is_root, typename WritableType>
558 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Tuple>,
559 WritableType out_it ) {
560 using tuple_t = typename JsonMember::sub_member_list;
561 return json_details::to_json_tuple_schema<tuple_t, is_root>(
562 out_it,
563 std::make_index_sequence<tuple_elements_pack<tuple_t>::size>{ } );
564 }
565
566 template<typename JsonMember, bool is_root, typename WritableType>
567 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Array>,
568 WritableType out_it ) {
569 if constexpr( not is_root ) {
570 out_it.put( '{' );
571 out_it.add_indent( );
572 }
573 out_it.next_member( );
574 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
575 out_it.next_member( );
576 out_it.write( "\"items\":", out_it.space );
577 using element_t = typename JsonMember::json_element_t;
578 out_it = to_json_schema<element_t>(
579 ParseTag<element_t::expected_type>{ }, out_it );
580 if constexpr( not is_root ) {
581 out_it.del_indent( );
582 }
583 out_it.next_member( );
584 if constexpr( not is_root ) {
585 out_it.put( '}' );
586 }
587 return out_it;
588 }
589
590 template<typename JsonMember, bool is_root, typename WritableType>
591 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Null>,
592 WritableType out_it ) {
593 using sub_member = typename JsonMember::member_type;
594 return to_json_schema<sub_member, is_root>(
595 ParseTag<sub_member::expected_type>{ }, out_it );
596 }
597
598 template<typename JsonMember, bool is_root, typename WritableType>
599 constexpr WritableType
600 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
601 WritableType out_it ) {
602 return to_json_schema<JsonMember, is_root>(
603 ParseTag<JsonParseTypes::Array>{ }, out_it );
604 }
605
606 template<typename JsonMember, bool is_root, typename WritableType>
607 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
608 WritableType out_it ) {
609 if constexpr( not is_root ) {
610 out_it.put( '{' );
611 out_it.add_indent( );
612 }
613 out_it.next_member( );
614 out_it = utils::output_kv( out_it, R"("type")", R"("object")" );
615 out_it.put( ',' );
616 out_it.next_member( );
617 out_it = utils::output_kv( out_it, R"("additionalProperties")", "" );
618 using element_t = typename JsonMember::json_element_t;
619 out_it = to_json_schema<element_t>(
620 ParseTag<element_t::expected_type>{ }, out_it );
621 if constexpr( not is_root ) {
622 out_it.del_indent( );
623 }
624 out_it.next_member( );
625 if constexpr( not is_root ) {
626 out_it.put( '}' );
627 }
628 return out_it;
629 }
630
631 template<typename JsonMember, bool is_root, typename WritableType>
632 constexpr WritableType
633 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
634 WritableType out_it ) {
635 if constexpr( not is_root ) {
636 out_it.put( '{' );
637 out_it.add_indent( );
638 }
639 out_it.next_member( );
640 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
641 out_it.next_member( );
642 out_it.write( "\"items\":", out_it.space );
643 using element_t = typename JsonMember::json_class_t;
644 out_it = to_json_schema<element_t>(
645 ParseTag<element_t::expected_type>{ }, out_it );
646 if constexpr( not is_root ) {
647 out_it.del_indent( );
648 }
649 out_it.next_member( );
650 if constexpr( not is_root ) {
651 out_it.put( '}' );
652 }
653 return out_it;
654 }
655
656 template<typename...>
657 struct variant_element_types;
658
659 template<typename... JsonElements>
660 struct variant_element_types<json_variant_type_list<JsonElements...>> {
661
662 template<typename JsonElement, typename WritableType>
663 static constexpr WritableType output_element( WritableType out_it,
664 bool &is_first ) {
665 if( not is_first ) {
666 out_it.put( ',' );
667 } else {
668 is_first = false;
669 }
670 out_it.next_member( );
671 return to_json_schema<JsonElement>(
672 ParseTag<JsonElement::expected_type>{ }, out_it );
673 }
674
675 template<typename WritableType>
676 static constexpr WritableType output_elements( WritableType out_it ) {
677 bool is_first = true;
678 return static_cast<WritableType>(
679 ( output_element<JsonElements>( out_it, is_first ), ... ) );
680 }
681 };
682
683 template<typename JsonMember, bool is_root, typename WritableType>
684 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Variant>,
685 WritableType out_it ) {
686 if constexpr( not is_root ) {
687 out_it.put( '{' );
688 out_it.add_indent( );
689 }
690 out_it.next_member( );
691 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
692 using elements_t = typename JsonMember::json_elements;
693 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
694 out_it.add_indent( );
695 out_it = variant_element_types<elements_t>::output_elements( out_it );
696 out_it.del_indent( );
697 out_it.next_member( );
698 }
699 out_it.put( ']' );
700 if constexpr( not is_root ) {
701 out_it.del_indent( );
702 }
703 out_it.next_member( );
704 if constexpr( not is_root ) {
705 out_it.put( '}' );
706 }
707 return out_it;
708 }
709
710 template<typename JsonMember, bool is_root, typename WritableType>
711 constexpr WritableType
712 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
713 WritableType out_it ) {
714 static_assert( not is_root,
715 "Attempt to have a tagged variant as root object. This "
716 "is unsupported" );
717 out_it.put( '{' );
718 out_it.add_indent( );
719 out_it.next_member( );
720 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
721 using elements_t = typename JsonMember::json_elements;
722 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
723 out_it.add_indent( );
724 out_it = variant_element_types<elements_t>::output_elements( out_it );
725 out_it.del_indent( );
726 out_it.next_member( );
727 }
728 out_it.put( ']' );
729 out_it.del_indent( );
730 out_it.next_member( );
731 out_it.put( '}' );
732 return out_it;
733 }
734
735 template<typename JsonMember, bool is_root, typename WritableType>
736 constexpr WritableType
737 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
738 WritableType out_it ) {
739 if constexpr( not is_root ) {
740 out_it.put( '{' );
741 out_it.add_indent( );
742 }
743 out_it.next_member( );
744 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
745 using elements_t = typename JsonMember::json_elements;
746 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
747 out_it.add_indent( );
748 out_it = variant_element_types<elements_t>::output_elements( out_it );
749 out_it.del_indent( );
750 out_it.next_member( );
751 }
752 out_it.put( ']' );
753 if constexpr( not is_root ) {
754 out_it.del_indent( );
755 }
756 out_it.next_member( );
757 if constexpr( not is_root ) {
758 out_it.put( '}' );
759 }
760 return out_it;
761 }
762 } // namespace json_details
763
772 template<typename T, typename WritableType, auto... PolicyFlags>
773 constexpr WritableType to_json_schema(
774 WritableType &it, std::string_view id, std::string_view title,
775 options::output_flags_t<PolicyFlags...> = options::output_flags<> ) {
776
777 auto out_it = json_details::make_output_iterator<PolicyFlags...>( it );
778
779 out_it.put( '{' );
780 out_it.add_indent( );
781 out_it.next_member( );
782 out_it = utils::output_kv(
783 out_it,
784 R"("$schema")",
785 R"("https://json-schema.org/draft/2020-12/schema",)" );
786 out_it.next_member( );
787 out_it = utils::output_kv( out_it, R"("$id")", "\"" );
788 out_it = utils::copy_to_iterator( out_it, id );
789 out_it = utils::copy_to_iterator( out_it, R"(",)" );
790 out_it.next_member( );
791 out_it = utils::output_kv( out_it, R"("title")", "\"" );
792 out_it = utils::copy_to_iterator( out_it, title );
793 out_it = utils::copy_to_iterator( out_it, R"(",)" );
794 using json_type = json_link_no_name<T>;
795 out_it = json_details::to_json_schema<json_type, true>(
797 out_it.del_indent( );
798 out_it.next_member( );
799 out_it.put( '}' );
800 return out_it.get( );
801 }
802
812 template<typename T, typename Result = std::string, auto... PolicyFlags>
813 constexpr Result
814 to_json_schema( std::string_view id, std::string_view title,
815 options::output_flags_t<PolicyFlags...> flags =
816 options::output_flags<> ) {
817 auto result = Result( );
818
819 (void)to_json_schema<T>( result, id, title, flags );
820 return result;
821 }
822 } // namespace DAW_JSON_VER
823} // namespace daw::json
@ Tuple
A variant type where the Switcher is based on a submember of the class being parsed.
static constexpr WriteableType output_kv(WriteableType it, std::string_view key, std::string_view value)
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20