DAW JSON Link
to_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 "daw_json_link_types.h"
13 
14 namespace daw::json {
15  inline namespace DAW_JSON_VER {
16  namespace json_details {
17 
18  template<typename JsonMember, bool is_root = false,
19  typename OutputIterator>
21  OutputIterator out_it ) {
22  if constexpr( not is_root ) {
23  *out_it++ = '{';
24  }
25  out_it = utils::copy_to_iterator( out_it, R"("type":"bool")" );
26  if constexpr( not is_root ) {
27  *out_it++ = '}';
28  }
29  return out_it;
30  }
31 
32  template<typename JsonMember, bool is_root = false,
33  typename OutputIterator>
35  OutputIterator out_it ) {
36  // TODO allow a trait to describe the valid literal types or if it
37  // matches one of the other predefined types
38  static_assert( JsonMember::custom_json_type == JsonCustomTypes::String );
39  if constexpr( not is_root ) {
40  *out_it++ = '{';
41  }
42  out_it = utils::copy_to_iterator( out_it, R"("type":"string")" );
43  if constexpr( not is_root ) {
44  *out_it++ = '}';
45  }
46  return out_it;
47  }
48 
49  template<typename JsonMember, bool is_root = false,
50  typename OutputIterator>
52  OutputIterator out_it ) {
53 
54  if constexpr( not is_root ) {
55  *out_it++ = '{';
56  }
57  out_it = utils::copy_to_iterator(
58  out_it, R"("type":"string","format":"date-time")" );
59  if constexpr( not is_root ) {
60  *out_it++ = '}';
61  }
62  return out_it;
63  }
64 
65  template<typename JsonMember, bool is_root = false,
66  typename OutputIterator>
68  OutputIterator out_it ) {
69 
70  if constexpr( not is_root ) {
71  *out_it++ = '{';
72  }
73  out_it = utils::copy_to_iterator( out_it, R"("type":"number")" );
74  if constexpr( not is_root ) {
75  *out_it++ = '}';
76  }
77  return out_it;
78  }
79 
80  template<typename JsonMember, bool is_root = false,
81  typename OutputIterator>
83  OutputIterator out_it ) {
84 
85  if constexpr( not is_root ) {
86  *out_it++ = '{';
87  }
88  out_it = utils::copy_to_iterator( out_it, R"("type":"integer")" );
89  if constexpr( not is_root ) {
90  *out_it++ = '}';
91  }
92  return out_it;
93  }
94 
95  template<typename JsonMember, bool is_root = false,
96  typename OutputIterator>
97  constexpr OutputIterator
99  OutputIterator out_it ) {
100 
101  if constexpr( not is_root ) {
102  *out_it++ = '{';
103  }
104  out_it = utils::copy_to_iterator( out_it, R"("type":"string")" );
105  if constexpr( not is_root ) {
106  *out_it++ = '}';
107  }
108  return out_it;
109  }
110 
111  template<typename JsonMember, bool is_root = false,
112  typename OutputIterator>
113  constexpr OutputIterator
115  OutputIterator out_it ) {
116 
117  if constexpr( not is_root ) {
118  *out_it++ = '{';
119  }
120  out_it = utils::copy_to_iterator( out_it, R"("type":"string")" );
121  if constexpr( not is_root ) {
122  *out_it++ = '}';
123  }
124  return out_it;
125  }
126 
127  template<typename JsonMember, bool is_root = false,
128  typename OutputIterator>
129  constexpr OutputIterator
131  OutputIterator out_it ) {
132  if constexpr( not is_root ) {
133  *out_it++ = '{';
134  }
135  out_it =
136  utils::copy_to_iterator( out_it, R"("type":"integer","minimum":0)" );
137  if constexpr( not is_root ) {
138  *out_it++ = '}';
139  }
140  return out_it;
141  }
142 
143  /***
144  * Output the schema of a json_class and it's members
145  * @tparam JsonMember A json_class type
146  * @tparam is_root Is this the root item in the schema.
147  * @tparam OutputIterator An iterator type that allows for assigning to
148  * the result of operator* and pre/post-fix incrementing
149  * @param out_it Current OutputIterator
150  * @return the last value of out_it
151  */
152  template<typename JsonMember, bool is_root = false,
153  typename OutputIterator>
155  OutputIterator out_it );
156 
157  /***
158  * Output the schema of a json_array and it's element type
159  * @tparam JsonMember A json_array type
160  * @tparam is_root Is this the root item in the schema.
161  * @tparam OutputIterator An iterator type that allows for assigning to
162  * the result of operator and pre/post-fix incrementing
163  * @param out_it Current OutputIterator
164  * @return the last value of out_it
165  */
166  template<typename JsonMember, bool is_root = false,
167  typename OutputIterator>
169  OutputIterator out_it );
170 
171  template<typename JsonMember, bool is_root = false,
172  typename OutputIterator>
173  constexpr OutputIterator
175  OutputIterator out_it );
176 
177  template<typename JsonMember, bool is_root = false,
178  typename OutputIterator>
179  constexpr OutputIterator
181  OutputIterator out_it );
182 
183  template<typename JsonMember, bool is_root = false,
184  typename OutputIterator>
185  constexpr OutputIterator
187  OutputIterator out_it );
188 
189  template<typename JsonMember, bool is_root = false,
190  typename OutputIterator>
191  constexpr OutputIterator
193  OutputIterator out_it );
194 
195  template<typename, typename>
197 
198  template<typename OutputIterator, typename... JsonMembers>
199  struct json_class_processor<OutputIterator,
200  json_member_list<JsonMembers...>> {
201 
202  static constexpr OutputIterator process( OutputIterator out_it ) {
203  out_it = utils::copy_to_iterator(
204  out_it, R"("type":"object","properties":{)" );
205  out_it = output_member_types( out_it );
206  out_it = utils::copy_to_iterator( out_it, R"(},"required":[)" );
207  out_it = output_required_members( out_it );
208  *out_it++ = ']';
209  return out_it;
210  }
211 
212  private:
213  static constexpr auto indexer =
214  std::index_sequence_for<JsonMembers...>{ };
215 
216  template<typename JsonMember>
217  static constexpr OutputIterator
218  output_member_type( OutputIterator &out_it, bool &is_first ) {
219  if( not is_first ) {
220  *out_it++ = ',';
221  } else {
222  is_first = false;
223  }
224  *out_it++ = '"';
225  out_it = utils::copy_to_iterator( out_it, JsonMember::name );
226  out_it = utils::copy_to_iterator( out_it, R"(":)" );
227  out_it = to_json_schema<JsonMember>(
228  ParseTag<JsonMember::base_expected_type>{ }, out_it );
229  return out_it;
230  }
231 
232  static constexpr OutputIterator
233  output_member_types( OutputIterator &out_it ) {
234  bool is_first = true;
235  return static_cast<OutputIterator>(
236  ( output_member_type<JsonMembers>( out_it, is_first ), ... ) );
237  }
238 
239  template<typename JsonMember>
240  static constexpr OutputIterator
241  output_required_member( OutputIterator &out_it, bool &is_first ) {
242  if constexpr( JsonMember::nullable == JsonNullable::MustExist ) {
243  if( not is_first ) {
244  *out_it++ = ',';
245  } else {
246  is_first = false;
247  }
248  *out_it++ = '"';
249  out_it = utils::copy_to_iterator( out_it, JsonMember::name );
250  *out_it++ = '"';
251  }
252  return out_it;
253  }
254 
255  static constexpr OutputIterator
256  output_required_members( OutputIterator &out_it ) {
257  bool is_first = true;
258  return ( output_required_member<JsonMembers>( out_it, is_first ),
259  ... );
260  }
261  };
262 
263  template<typename OutputIterator, typename... JsonMembers>
264  struct json_class_processor<OutputIterator,
265  json_ordered_member_list<JsonMembers...>> {
266 
267  static constexpr OutputIterator process( OutputIterator out_it ) {
268  out_it = utils::copy_to_iterator(
269  out_it, R"("type":"object","properties":{)" );
270  out_it = output_member_types( out_it );
271  out_it = utils::copy_to_iterator( out_it, R"(},"required":[)" );
272  out_it = output_required_members( out_it );
273  *out_it++ = ']';
274  return out_it;
275  }
276  };
277  template<typename JsonMember, bool is_root, typename OutputIterator>
279  OutputIterator out_it ) {
280  if constexpr( not is_root ) {
281  *out_it++ = '{';
282  }
283 
284  using json_class_processor_t = json_class_processor<
285  OutputIterator,
287 
288  out_it = json_class_processor_t::process( out_it );
289 
290  if constexpr( not is_root ) {
291  *out_it++ = '}';
292  }
293  return out_it;
294  }
295 
296  template<typename JsonMember, bool is_root, typename OutputIterator>
298  OutputIterator out_it ) {
299  if constexpr( not is_root ) {
300  *out_it++ = '{';
301  }
302  out_it =
303  utils::copy_to_iterator( out_it, R"("type":"array","items":)" );
304  using element_t = typename JsonMember::json_element_t;
305  out_it = to_json_schema<element_t>(
307  if constexpr( not is_root ) {
308  *out_it++ = '}';
309  }
310  return out_it;
311  }
312 
313  } // namespace json_details
314  } // namespace DAW_JSON_VER
315 } // namespace daw::json
316 
317 namespace daw::json {
318  inline namespace DAW_JSON_VER {
319  template<typename T, typename OutputIterator>
320  constexpr OutputIterator to_json_schema( OutputIterator out_it,
321  std::string_view id,
322  std::string_view title ) {
323  *out_it++ = '{';
324  out_it = utils::copy_to_iterator(
325  out_it,
326  R"("$schema":"https://json-schema.org/draft/2020-12/schema",)" );
327  out_it = utils::copy_to_iterator( out_it, R"("$id":")" );
328  out_it = utils::copy_to_iterator( out_it, id );
329  out_it = utils::copy_to_iterator( out_it, R"(","title":")" );
330  out_it = utils::copy_to_iterator( out_it, title );
331  out_it = utils::copy_to_iterator( out_it, R"(",)" );
332 
333  using json_type = json_link_no_name<T>;
334  out_it = json_details::to_json_schema<json_type, true>(
336  *out_it++ = '}';
337  return out_it;
338  }
339 
340  template<typename T>
341  std::string to_json_schema( std::string_view id, std::string_view title ) {
342  auto result = std::string( );
343  (void)to_json_schema<T>( std::back_inserter( result ), id, title );
344  return result;
345  }
346 
347  } // namespace DAW_JSON_VER
348 } // namespace daw::json
struct daw::json::DAW_JSON_VER::json_details::json_class_processor< OutputIterator, json_member_list< JsonMembers... > > output_required_members(OutputIterator &out_it)
Definition: to_json_schema.h:256
constexpr OutputIterator to_json_schema(ParseTag< JsonParseTypes::Bool >, OutputIterator out_it)
Definition: to_json_schema.h:20
constexpr OutputIterator copy_to_iterator(OutputIterator it, Container const &container)
Definition: to_daw_json_string.h:393
constexpr OutputIterator to_json_schema(ParseTag< JsonParseTypes::Class >, OutputIterator out_it)
Definition: to_json_schema.h:278
typename json_data_contract< T >::type json_data_contract_trait_t
Definition: daw_json_traits.h:132
std::integral_constant< JsonParseTypes, v > ParseTag
Definition: daw_json_enums.h:119
json_details::ensure_mapped_t< json_details::json_deduced_type< T > > json_link_no_name
Definition: daw_json_link_types.h:1558
Definition: daw_from_json.h:22
static constexpr OutputIterator process(OutputIterator out_it)
Definition: to_json_schema.h:267
static constexpr OutputIterator process(OutputIterator out_it)
Definition: to_json_schema.h:202
Definition: daw_json_link_types.h:33
Definition: daw_json_link_types.h:202
static constexpr OutputIterator process(OutputIterator out_it)
Definition: to_json_schema.h:258
#define DAW_JSON_VER
Definition: version.h:11