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