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>, WritableType out_it ) {
171 return to_json_schema<JsonMember, is_root>(
172 ParseTag<JsonParseTypes::StringEscaped>{ }, out_it );
173 }
174
175 template<typename JsonMember, bool is_root = false, typename WritableType>
176 constexpr WritableType
177 to_json_schema( ParseTag<JsonParseTypes::StringRaw>,
178 WritableType out_it ) {
179
180 if constexpr( not is_root ) {
181 out_it.put( '{' );
182 out_it.add_indent( );
183 out_it.next_member( );
184 }
185 out_it = utils::output_kv( out_it, R"("type")", R"("string")" );
186 if constexpr( not is_root ) {
187 out_it.del_indent( );
188 }
189 out_it.next_member( );
190 if constexpr( not is_root ) {
191 out_it.put( '}' );
192 }
193 return out_it;
194 }
195
196 template<typename JsonMember, bool is_root = false, typename WritableType>
197 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Unsigned>,
198 WritableType out_it ) {
199 if constexpr( not is_root ) {
200 out_it.put( '{' );
201 out_it.add_indent( );
202 out_it.next_member( );
203 }
204 out_it = utils::output_kv( out_it, R"("type")", R"("integer")" );
205 out_it.put( ',' );
206 out_it.next_member( );
207 out_it = utils::output_kv( out_it, R"("minimum")", "0" );
208 if constexpr( not is_root ) {
209 out_it.del_indent( );
210 }
211 out_it.next_member( );
212 if constexpr( not is_root ) {
213 out_it.put( '}' );
214 }
215 return out_it;
216 }
217
218 /***
219 * Output the schema of a json_class and it's members
220 * @tparam JsonMember A json_class type
221 * @tparam is_root Is this the root item in the schema.
222 * @tparam WritableType An iterator type that allows for assigning to
223 * the result of operator* and pre/post-fix incrementing
224 * @param out_it Current WritableType
225 * @return the last value of out_it
226 */
227 template<typename JsonMember, bool is_root = false, typename WritableType>
228 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Class>,
229 WritableType out_it );
230
231 /***
232 * Output the schema of a json_array and it's element type
233 * @tparam JsonMember A json_array type
234 * @tparam is_root Is this the root item in the schema.
235 * @tparam WritableType An iterator type that allows for assigning to
236 * the result of operator and pre/post-fix incrementing
237 * @param out_it Current WritableType
238 * @return the last value of out_it
239 */
240 template<typename JsonMember, bool is_root = false, typename WritableType>
241 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Array>,
242 WritableType out_it );
243
244 template<typename JsonMember, bool is_root = false, typename WritableType>
245 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Null>,
246 WritableType out_it );
247
248 template<typename JsonMember, bool is_root = false, typename WritableType>
249 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Tuple>,
250 WritableType out_it );
251
252 template<typename JsonMember, bool is_root = false, typename WritableType>
253 constexpr WritableType
254 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
255 WritableType out_it );
256
257 template<typename JsonMember, bool is_root = false, typename WritableType>
258 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
259 WritableType out_it );
260
261 template<typename JsonMember, bool is_root = false, typename WritableType>
262 constexpr WritableType
263 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
264 WritableType out_it );
265
266 template<typename JsonMember, bool is_root = false, typename WritableType>
267 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Variant>,
268 WritableType out_it );
269
270 template<typename JsonMember, bool is_root = false, typename WritableType>
271 constexpr WritableType
272 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
273 WritableType out_it );
274
275 template<typename JsonMember, bool is_root = false, typename WritableType>
276 constexpr WritableType
277 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
278 WritableType out_it );
279
280 template<typename, typename>
281 struct json_class_processor;
282
287 template<typename WritableType, typename... JsonMembers>
288 struct json_class_processor<WritableType,
289 json_member_list<JsonMembers...>> {
290
291 static constexpr std::size_t size = sizeof...( JsonMembers );
292
297 static constexpr WritableType process( WritableType out_it ) {
298 out_it = utils::output_kv( out_it, R"("type")", R"("object")" );
299 out_it.put( ',' );
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( );
309 }
310 out_it.put( '}' );
311 out_it.put( ',' );
312 out_it.next_member( );
313 out_it = utils::output_kv( out_it, R"("required")", "[" );
314 if constexpr( not is_empty_pack_v<JsonMembers...> ) {
315 out_it.add_indent( );
316 out_it = output_required_members( out_it );
317 out_it.del_indent( );
318 out_it.next_member( );
319 }
320 out_it.put( ']' );
321 if constexpr( ( has_dependent_member_v<JsonMembers> or ... ) ) {
322 out_it.put( ',' );
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<WritableType>(
328 ( output_dependency<
329 json_link_no_name<json_link_no_name<JsonMembers>>>(
330 out_it, is_first ),
331 ... ) );
332 out_it.del_indent( );
333 if( not is_first ) {
334 // If we have at least 1 dependent member, is_first will be false
335 out_it.next_member( );
336 }
337 out_it.put( '}' );
338 }
339 return out_it;
340 }
341
342 private:
343 static constexpr auto indexer =
344 std::index_sequence_for<JsonMembers...>{ };
345
352 template<typename JsonMember, std::size_t Idx>
353 static constexpr WritableType output_member_type( WritableType &out_it,
354 bool *seen ) {
355 if( seen[Idx] ) {
356 return out_it;
357 } else {
358 seen[Idx] = true;
359 }
360
361 out_it.write( "\"", JsonMember::name, "\":", out_it.space );
362 out_it = to_json_schema<JsonMember>(
363 ParseTag<JsonMember::expected_type>{ }, out_it );
364 if constexpr( Idx + 1 < sizeof...( JsonMembers ) ) {
365 out_it.put( ',' );
366 out_it.next_member( );
367 }
368 return out_it;
369 }
370
371 template<std::size_t... Is>
372 DAW_ATTRIB_INLINE static constexpr WritableType
373 output_member_types( WritableType &out_it,
374 std::index_sequence<Is...> ) {
375 bool seen[sizeof...( JsonMembers )]{ };
376 return static_cast<WritableType>(
377 ( output_member_type<JsonMembers, Is>( out_it, seen ), ... ) );
378 }
379
380 template<typename JsonMember>
381 static constexpr WritableType
382 output_required_member( WritableType &out_it, bool &is_first ) {
383 if constexpr( not is_json_nullable_v<JsonMember> ) {
384 if( not is_first ) {
385 out_it.put( ',' );
386 } else {
387 is_first = false;
388 }
389 out_it.next_member( );
390 out_it.put( '"' );
391 out_it = utils::copy_to_iterator( out_it, JsonMember::name );
392 out_it.put( '"' );
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( "\"", JsonMember::name, "\":", out_it.space, "[" );
408 out_it.add_indent( );
409 out_it.next_member( );
410 out_it.write( "\"", dependent_member_t<JsonMember>::name, "\"" );
411 out_it.del_indent( );
412 out_it.next_member( );
413 out_it.put( ']' );
414 }
415 return out_it;
416 }
417
418 static constexpr WritableType
419 output_required_members( WritableType &out_it ) {
420 bool is_first = true;
421 return ( output_required_member<json_link_no_name<JsonMembers>>(
422 out_it, is_first ),
423 ... );
424 }
425 };
426
427 template<typename WritableType, typename... JsonMembers>
428 struct json_class_processor<WritableType,
429 json_tuple_member_list<JsonMembers...>> {
430
431 static constexpr std::size_t size = sizeof...( JsonMembers );
432 static constexpr WritableType process( WritableType out_it ) {
433
434 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
435 out_it.next_member( );
436 out_it = utils::output_kv( out_it, R"("items")", "[" );
437 if constexpr( sizeof...( JsonMembers ) > 0 ) {
438 out_it.add_indent( );
439 out_it = output_member_types( out_it );
440 out_it.del_indent( );
441 out_it.next_member( );
442 }
443 out_it.put( ']' );
444
445 static_assert(
446 not( ( json_link_no_name<JsonMembers>::expected_type ==
447 JsonParseTypes::VariantTagged ) or
448 ... ),
449 "A tagged variant is not supported in a tuple/ordered json "
450 "class" );
451 return out_it;
452 }
453
454 static constexpr WritableType
455 output_member_types( WritableType &out_it ) {
456 bool is_first = true;
457 return static_cast<WritableType>(
458 ( output_member_type<json_link_no_name<JsonMembers>>( out_it,
459 is_first ),
460 ... ) );
461 }
462
463 template<typename JsonMember>
464 static constexpr WritableType output_member_type( WritableType &out_it,
465 bool &is_first ) {
466 if( not is_first ) {
467 out_it.put( ',' );
468 } else {
469 is_first = false;
470 }
471 out_it.next_member( );
472 out_it = to_json_schema<JsonMember>(
473 ParseTag<JsonMember::expected_type>{ }, out_it );
474 return out_it;
475 }
476 };
477
478 template<typename JsonMember, bool is_root, typename WritableType>
479 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Class>,
480 WritableType out_it ) {
481 using json_class_processor_t = json_class_processor<
482 WritableType,
483 json_data_contract_trait_t<json_base_type_t<JsonMember>>>;
484
485 if constexpr( not is_root ) {
486 out_it.put( '{' );
487 out_it.add_indent( );
488 }
489 if constexpr( json_class_processor_t::size > 0 ) {
490 out_it.next_member( );
491 out_it = json_class_processor_t::process( out_it );
492 }
493 if constexpr( not is_root ) {
494 out_it.del_indent( );
495 }
496 if constexpr( not is_root ) {
497 out_it.next_member( );
498 out_it.put( '}' );
499 }
500 return out_it;
501 }
502
503 namespace json_details {
504 template<typename Tuple, bool is_root, typename WritableType,
505 std::size_t... Is>
506 DAW_ATTRIB_INLINE constexpr WritableType
507 to_json_tuple_schema( WritableType out_it,
508 std::index_sequence<Is...> ) {
509 if constexpr( not is_root ) {
510 out_it.put( '{' );
511 out_it.add_indent( );
512 }
513 out_it.next_member( );
514 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
515 out_it.next_member( );
516 out_it = utils::output_kv( out_it, R"("items")", "[" );
517 if constexpr( sizeof...( Is ) > 0 ) {
518 out_it.add_indent( );
519 bool is_first = true;
520 auto const process_member = [&is_first, &out_it]( auto Idx ) {
521 if( not is_first ) {
522 out_it.put( ',' );
523 } else {
524 is_first = false;
525 }
526 out_it.next_member( );
527 using index = daw::constant<DAW_TYPEOF( Idx )::value>;
528 using pack_element = tuple_elements_pack<Tuple>;
529 using JsonMember = json_deduced_type<
530 typename pack_element::template element_t<index::value>>;
531
532 out_it = to_json_schema<JsonMember>(
533 ParseTag<JsonMember::expected_type>{ }, out_it );
534 };
535
536 daw::empty_t expander[] = {
537 ( process_member( daw::constant_v<Is> ), daw::empty_t{ } )...,
538 daw::empty_t{ } };
539 (void)expander;
540 out_it.del_indent( );
541 out_it.next_member( );
542 }
543 out_it.put( ']' );
544 if constexpr( not is_root ) {
545 out_it.del_indent( );
546 }
547 out_it.next_member( );
548 if constexpr( not is_root ) {
549 out_it.put( '}' );
550 }
551 return out_it;
552 }
553 } // namespace json_details
554
555 template<typename JsonMember, bool is_root, typename WritableType>
556 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Tuple>,
557 WritableType out_it ) {
558 using tuple_t = typename JsonMember::sub_member_list;
559 return json_details::to_json_tuple_schema<tuple_t, is_root>(
560 out_it,
561 std::make_index_sequence<tuple_elements_pack<tuple_t>::size>{ } );
562 }
563
564 template<typename JsonMember, bool is_root, typename WritableType>
565 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Array>,
566 WritableType out_it ) {
567 if constexpr( not is_root ) {
568 out_it.put( '{' );
569 out_it.add_indent( );
570 }
571 out_it.next_member( );
572 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
573 out_it.next_member( );
574 out_it.write( "\"items\":", out_it.space );
575 using element_t = typename JsonMember::json_element_t;
576 out_it = to_json_schema<element_t>(
577 ParseTag<element_t::expected_type>{ }, out_it );
578 if constexpr( not is_root ) {
579 out_it.del_indent( );
580 }
581 out_it.next_member( );
582 if constexpr( not is_root ) {
583 out_it.put( '}' );
584 }
585 return out_it;
586 }
587
588 template<typename JsonMember, bool is_root, typename WritableType>
589 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Null>,
590 WritableType out_it ) {
591 using sub_member = typename JsonMember::member_type;
592 return to_json_schema<sub_member, is_root>(
593 ParseTag<sub_member::expected_type>{ }, out_it );
594 }
595
596 template<typename JsonMember, bool is_root, typename WritableType>
597 constexpr WritableType
598 to_json_schema( ParseTag<JsonParseTypes::SizedArray>,
599 WritableType out_it ) {
600 return to_json_schema<JsonMember, is_root>(
601 ParseTag<JsonParseTypes::Array>{ }, out_it );
602 }
603
604 template<typename JsonMember, bool is_root, typename WritableType>
605 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::KeyValue>,
606 WritableType out_it ) {
607 if constexpr( not is_root ) {
608 out_it.put( '{' );
609 out_it.add_indent( );
610 }
611 out_it.next_member( );
612 out_it = utils::output_kv( out_it, R"("type")", R"("object")" );
613 out_it.put( ',' );
614 out_it.next_member( );
615 out_it = utils::output_kv( out_it, R"("additionalProperties")", "" );
616 using element_t = typename JsonMember::json_element_t;
617 out_it = to_json_schema<element_t>(
618 ParseTag<element_t::expected_type>{ }, out_it );
619 if constexpr( not is_root ) {
620 out_it.del_indent( );
621 }
622 out_it.next_member( );
623 if constexpr( not is_root ) {
624 out_it.put( '}' );
625 }
626 return out_it;
627 }
628
629 template<typename JsonMember, bool is_root, typename WritableType>
630 constexpr WritableType
631 to_json_schema( ParseTag<JsonParseTypes::KeyValueArray>,
632 WritableType out_it ) {
633 if constexpr( not is_root ) {
634 out_it.put( '{' );
635 out_it.add_indent( );
636 }
637 out_it.next_member( );
638 out_it = utils::output_kv( out_it, R"("type")", R"("array",)" );
639 out_it.next_member( );
640 out_it.write( "\"items\":", out_it.space );
641 using element_t = typename JsonMember::json_class_t;
642 out_it = to_json_schema<element_t>(
643 ParseTag<element_t::expected_type>{ }, out_it );
644 if constexpr( not is_root ) {
645 out_it.del_indent( );
646 }
647 out_it.next_member( );
648 if constexpr( not is_root ) {
649 out_it.put( '}' );
650 }
651 return out_it;
652 }
653
654 template<typename...>
655 struct variant_element_types;
656
657 template<typename... JsonElements>
658 struct variant_element_types<json_variant_type_list<JsonElements...>> {
659
660 template<typename JsonElement, typename WritableType>
661 static constexpr WritableType output_element( WritableType out_it,
662 bool &is_first ) {
663 if( not is_first ) {
664 out_it.put( ',' );
665 } else {
666 is_first = false;
667 }
668 out_it.next_member( );
669 return to_json_schema<JsonElement>(
670 ParseTag<JsonElement::expected_type>{ }, out_it );
671 }
672
673 template<typename WritableType>
674 static constexpr WritableType output_elements( WritableType out_it ) {
675 bool is_first = true;
676 return static_cast<WritableType>(
677 ( output_element<JsonElements>( out_it, is_first ), ... ) );
678 }
679 };
680
681 template<typename JsonMember, bool is_root, typename WritableType>
682 constexpr WritableType to_json_schema( ParseTag<JsonParseTypes::Variant>,
683 WritableType out_it ) {
684 if constexpr( not is_root ) {
685 out_it.put( '{' );
686 out_it.add_indent( );
687 }
688 out_it.next_member( );
689 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
690 using elements_t = typename JsonMember::json_elements;
691 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
692 out_it.add_indent( );
693 out_it = variant_element_types<elements_t>::output_elements( out_it );
694 out_it.del_indent( );
695 out_it.next_member( );
696 }
697 out_it.put( ']' );
698 if constexpr( not is_root ) {
699 out_it.del_indent( );
700 }
701 out_it.next_member( );
702 if constexpr( not is_root ) {
703 out_it.put( '}' );
704 }
705 return out_it;
706 }
707
708 template<typename JsonMember, bool is_root, typename WritableType>
709 constexpr WritableType
710 to_json_schema( ParseTag<JsonParseTypes::VariantTagged>,
711 WritableType out_it ) {
712 static_assert( not is_root,
713 "Attempt to have a tagged variant as root object. This "
714 "is unsupported" );
715 out_it.put( '{' );
716 out_it.add_indent( );
717 out_it.next_member( );
718 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
719 using elements_t = typename JsonMember::json_elements;
720 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
721 out_it.add_indent( );
722 out_it = variant_element_types<elements_t>::output_elements( out_it );
723 out_it.del_indent( );
724 out_it.next_member( );
725 }
726 out_it.put( ']' );
727 out_it.del_indent( );
728 out_it.next_member( );
729 out_it.put( '}' );
730 return out_it;
731 }
732
733 template<typename JsonMember, bool is_root, typename WritableType>
734 constexpr WritableType
735 to_json_schema( ParseTag<JsonParseTypes::VariantIntrusive>,
736 WritableType out_it ) {
737 if constexpr( not is_root ) {
738 out_it.put( '{' );
739 out_it.add_indent( );
740 }
741 out_it.next_member( );
742 out_it = utils::output_kv( out_it, R"("oneOf")", "[" );
743 using elements_t = typename JsonMember::json_elements;
744 if constexpr( daw::pack_size_v<elements_t> != 0 ) {
745 out_it.add_indent( );
746 out_it = variant_element_types<elements_t>::output_elements( out_it );
747 out_it.del_indent( );
748 out_it.next_member( );
749 }
750 out_it.put( ']' );
751 if constexpr( not is_root ) {
752 out_it.del_indent( );
753 }
754 out_it.next_member( );
755 if constexpr( not is_root ) {
756 out_it.put( '}' );
757 }
758 return out_it;
759 }
760 } // namespace json_details
761
770 template<typename T, typename WritableType, auto... PolicyFlags>
771 constexpr WritableType to_json_schema(
772 WritableType &it, std::string_view id, std::string_view title,
773 options::output_flags_t<PolicyFlags...> = options::output_flags<> ) {
774
775 auto out_it = json_details::make_output_iterator<PolicyFlags...>( it );
776
777 out_it.put( '{' );
778 out_it.add_indent( );
779 out_it.next_member( );
780 out_it = utils::output_kv(
781 out_it,
782 R"("$schema")",
783 R"("https://json-schema.org/draft/2020-12/schema",)" );
784 out_it.next_member( );
785 out_it = utils::output_kv( out_it, R"("$id")", "\"" );
786 out_it = utils::copy_to_iterator( out_it, id );
787 out_it = utils::copy_to_iterator( out_it, R"(",)" );
788 out_it.next_member( );
789 out_it = utils::output_kv( out_it, R"("title")", "\"" );
790 out_it = utils::copy_to_iterator( out_it, title );
791 out_it = utils::copy_to_iterator( out_it, R"(",)" );
792 using json_type = json_link_no_name<T>;
793 out_it = json_details::to_json_schema<json_type, true>(
795 out_it.del_indent( );
796 out_it.next_member( );
797 out_it.put( '}' );
798 return out_it.get( );
799 }
800
810 template<typename T, typename Result = std::string, auto... PolicyFlags>
811 constexpr Result
812 to_json_schema( std::string_view id, std::string_view title,
813 options::output_flags_t<PolicyFlags...> flags =
814 options::output_flags<> ) {
815 auto result = Result( );
816
817 (void)to_json_schema<T>( result, id, title, flags );
818 return result;
819 }
820 } // namespace DAW_JSON_VER
821} // 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)
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20