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