32 inline std::string matchEnum(
const std::vector<std::string>& enums,
36 value >= 0 &&
static_cast<size_t>(value) < enums.size();
37 return inRange ? enums[
static_cast<size_t>(value)] :
"InvalidEnum";
45 std::string camelCaseToSnakeCase(
const std::string& camelCase)
50 std::string snakeCaseToCamelCase(
const std::string& snakeCase)
56 rapidjson::Value make_value_string(
57 const std::string& str, rapidjson::Document::AllocatorType& allocator)
60 val.SetString(str.c_str(), str.length(), allocator);
65 rapidjson::Value make_json_string(
const std::string& camelCase,
66 rapidjson::Document::AllocatorType& allocator)
68 return make_value_string(camelCaseToSnakeCase(camelCase), allocator);
72 void addDefaultValue(rapidjson::Document& document,
73 rapidjson::Document::AllocatorType& allocator,
76 document.AddMember(rapidjson::StringRef(
"default"), value, allocator);
80 void addDefaultValue(rapidjson::Document& document,
81 rapidjson::Document::AllocatorType& allocator,
82 const std::string& value)
84 document.AddMember(rapidjson::StringRef(
"default"),
85 make_value_string(value, allocator).Move(), allocator);
88 template <
typename T,
size_t S>
89 void addDefaultValueArray(rapidjson::Document& document,
90 rapidjson::Document::AllocatorType& allocator,
91 const std::array<T, S>& value)
93 rapidjson::Value arr(rapidjson::kArrayType);
94 for (
const auto v : value)
95 arr.PushBack(v, allocator);
96 document.AddMember(rapidjson::StringRef(
"default"), arr, allocator);
100 void addDefaultValue(rapidjson::Document& document,
101 rapidjson::Document::AllocatorType& allocator,
102 const std::array<double, 2>& value)
104 addDefaultValueArray(document, allocator, value);
108 void addDefaultValue(rapidjson::Document& document,
109 rapidjson::Document::AllocatorType& allocator,
110 const std::array<int32_t, 2>& value)
112 addDefaultValueArray(document, allocator, value);
115 void addDefaultValue(rapidjson::Document& document,
116 rapidjson::Document::AllocatorType& allocator,
117 const std::array<double, 3>& value)
119 addDefaultValueArray(document, allocator, value);
122 void addDefaultValue(rapidjson::Document& document,
123 rapidjson::Document::AllocatorType& allocator,
124 const std::array<int32_t, 3>& value)
126 addDefaultValueArray(document, allocator, value);
129 void addDefaultValue(rapidjson::Document& document,
130 rapidjson::Document::AllocatorType& allocator,
131 const std::array<double, 4>& value)
133 addDefaultValueArray(document, allocator, value);
138 template <
typename T>
139 void _addPropertySchema(
const Property& prop, rapidjson::Value& properties,
140 rapidjson::Document::AllocatorType& allocator)
142 using namespace rapidjson;
145 if (prop.enums.empty())
147 auto value = prop.get<T>();
148 jsonSchema = staticjson::export_json_schema(&value, &allocator);
149 jsonSchema.AddMember(StringRef(
"title"),
150 StringRef(prop.metaData.label.c_str()), allocator);
151 addDefaultValue(jsonSchema, allocator, value);
152 jsonSchema.AddMember(StringRef(
"readOnly"), prop.readOnly(), allocator);
153 const auto minValue = prop.min<T>();
154 const auto maxValue = prop.max<T>();
155 const bool hasLimits = maxValue - minValue != 0;
158 if (jsonSchema.HasMember(
"minimum"))
159 jsonSchema[
"minimum"] = minValue;
161 jsonSchema.AddMember(StringRef(
"minimum"), minValue, allocator);
163 if (jsonSchema.HasMember(
"maximum"))
164 jsonSchema[
"maximum"] = maxValue;
166 jsonSchema.AddMember(StringRef(
"maximum"), maxValue, allocator);
170 if (jsonSchema.HasMember(
"minimum"))
171 jsonSchema.RemoveMember(
"minimum");
172 if (jsonSchema.HasMember(
"maximum"))
173 jsonSchema.RemoveMember(
"maximum");
178 jsonSchema.SetObject();
179 jsonSchema.AddMember(StringRef(
"type"), StringRef(
"string"), allocator);
180 jsonSchema.AddMember(StringRef(
"title"),
181 StringRef(prop.metaData.label.c_str()), allocator);
182 jsonSchema.AddMember(StringRef(
"readOnly"), prop.readOnly(), allocator);
185 auto value = prop.get<int32_t>();
186 const auto valueStr = matchEnum(prop.enums, value);
187 addDefaultValue(jsonSchema, allocator, valueStr);
189 Value enumerations(kArrayType);
190 for (
const auto& name : prop.enums)
191 enumerations.PushBack(StringRef(name.data(), name.size()),
193 jsonSchema.AddMember(StringRef(
"enum"), enumerations, allocator);
195 properties.AddMember(make_json_string(prop.name, allocator).Move(),
196 jsonSchema, allocator);
202 void _addPropertySchema<bool>(
const Property& prop,
203 rapidjson::Value& properties,
204 rapidjson::Document::AllocatorType& allocator)
206 using namespace rapidjson;
207 auto value = prop.get<
bool>();
208 auto jsonSchema = staticjson::export_json_schema(&value, &allocator);
209 jsonSchema.AddMember(StringRef(
"title"),
210 StringRef(prop.metaData.label.c_str()), allocator);
211 addDefaultValue(jsonSchema, allocator, value);
212 jsonSchema.AddMember(StringRef(
"readOnly"), prop.readOnly(), allocator);
213 properties.AddMember(make_json_string(prop.name, allocator).Move(),
214 jsonSchema, allocator);
220 void _addPropertySchema<std::string>(
221 const Property& prop, rapidjson::Value& properties,
222 rapidjson::Document::AllocatorType& allocator)
224 using namespace rapidjson;
226 const bool isEnum = !prop.enums.empty();
227 auto value = prop.get<std::string>();
233 jsonSchema.SetObject();
234 jsonSchema.AddMember(StringRef(
"type"), StringRef(
"string"), allocator);
235 Value enumerations(kArrayType);
236 for (
const auto& name : prop.enums)
237 enumerations.PushBack(StringRef(name.data(), name.size()),
239 jsonSchema.AddMember(StringRef(
"enum"), enumerations, allocator);
243 jsonSchema = staticjson::export_json_schema(&value, &allocator);
246 addDefaultValue(jsonSchema, allocator, value);
247 jsonSchema.AddMember(StringRef(
"readOnly"), prop.readOnly(), allocator);
248 jsonSchema.AddMember(StringRef(
"title"),
249 StringRef(prop.metaData.label.c_str()), allocator);
250 properties.AddMember(make_json_string(prop.name, allocator).Move(),
251 jsonSchema, allocator);
256 template <
typename T,
int S>
257 void _addArrayPropertySchema(
const Property& prop, rapidjson::Value& properties,
258 rapidjson::Document::AllocatorType& allocator)
260 using namespace rapidjson;
261 auto value = prop.get<std::array<T, S>>();
262 auto jsonSchema = staticjson::export_json_schema(&value, &allocator);
263 jsonSchema.AddMember(StringRef(
"title"),
264 StringRef(prop.metaData.label.c_str()), allocator);
265 addDefaultValue(jsonSchema, allocator, value);
267 properties.AddMember(make_json_string(prop.name, allocator).Move(),
268 jsonSchema, allocator);
272 template <
typename T>
273 void _arrayPropertyToJson(rapidjson::Document& document, Property& prop)
275 rapidjson::Value array(rapidjson::kArrayType);
276 for (
const auto& val : prop.get<T>())
277 array.PushBack(val, document.GetAllocator());
280 make_json_string(prop.name, document.GetAllocator()).Move(), array,
281 document.GetAllocator());
288 const std::string& title,
289 rapidjson::Document::AllocatorType& allocator,
290 rapidjson::Value& propSchema)
292 using namespace rapidjson;
293 propSchema.AddMember(StringRef(
"title"), StringRef(title.c_str()),
295 propSchema.AddMember(StringRef(
"type"), StringRef(
"object"), allocator);
297 Value properties(kObjectType);
303 _addPropertySchema<double>(*prop, properties, allocator);
306 _addPropertySchema<int32_t>(*prop, properties, allocator);
309 _addPropertySchema<std::string>(*prop, properties, allocator);
312 _addPropertySchema<bool>(*prop, properties, allocator);
315 _addArrayPropertySchema<double, 2>(*prop, properties, allocator);
318 _addArrayPropertySchema<int32_t, 2>(*prop, properties, allocator);
321 _addArrayPropertySchema<double, 3>(*prop, properties, allocator);
324 _addArrayPropertySchema<int32_t, 3>(*prop, properties, allocator);
327 _addArrayPropertySchema<double, 4>(*prop, properties, allocator);
332 propSchema.AddMember(StringRef(
"properties"), properties, allocator);
338 const std::vector<std::pair<std::string, PropertyMap>>& objs,
339 rapidjson::Document::AllocatorType& allocator, rapidjson::Value& oneOf)
341 using namespace rapidjson;
342 for (
const auto& obj : objs)
344 Value propSchema(kObjectType);
346 oneOf.PushBack(propSchema, allocator);
354 const std::vector<std::pair<std::string, PropertyMap>>& objs)
356 using namespace rapidjson;
358 auto& allocator = schema.GetAllocator();
360 Value returns(kObjectType);
361 Value oneOf(kArrayType);
363 returns.AddMember(StringRef(
"oneOf"), oneOf, allocator);
364 schema.AddMember(StringRef(
"returns"), returns, allocator);
366 Value params(kArrayType);
367 schema.AddMember(StringRef(
"params"), params, allocator);
370 Writer<StringBuffer> writer(buffer);
371 schema.Accept(writer);
372 return buffer.GetString();
379 using namespace rapidjson;
381 auto& allocator = schema.GetAllocator();
383 Value returns(kObjectType);
385 schema.AddMember(StringRef(
"returns"), returns, allocator);
387 Value params(kArrayType);
388 schema.AddMember(StringRef(
"params"), params, allocator);
391 Writer<StringBuffer> writer(buffer);
392 schema.Accept(writer);
393 return buffer.GetString();
402 using namespace rapidjson;
404 auto& allocator = schema.GetAllocator();
406 Value returns(kObjectType);
408 schema.AddMember(StringRef(
"returns"), returns, allocator);
410 Value params(kArrayType);
411 Value param(kObjectType);
413 params.PushBack(param, allocator);
414 schema.AddMember(StringRef(
"params"), params, allocator);
417 Writer<StringBuffer> writer(buffer);
418 schema.Accept(writer);
419 return buffer.GetString();
426 const std::vector<std::pair<std::string, PropertyMap>>& objs)
428 using namespace rapidjson;
430 auto& allocator = schema.GetAllocator();
433 auto retSchema = staticjson::export_json_schema(&retVal);
434 schema.AddMember(StringRef(
"returns"), retSchema, allocator);
436 Value params(kArrayType);
437 Value oneOf(kArrayType);
438 Value returns(kObjectType);
440 returns.AddMember(StringRef(
"oneOf"), oneOf, allocator);
441 params.PushBack(returns, allocator);
442 schema.AddMember(StringRef(
"params"), params, allocator);
445 Writer<StringBuffer> writer(buffer);
446 schema.Accept(writer);
447 return buffer.GetString();
455 using namespace rapidjson;
457 auto& allocator = schema.GetAllocator();
460 auto retSchema = staticjson::export_json_schema(&retVal);
461 schema.AddMember(StringRef(
"returns"), retSchema, allocator);
463 Value params(kArrayType);
464 Value returns(kObjectType);
466 params.PushBack(returns, allocator);
467 schema.AddMember(StringRef(
"params"), params, allocator);
470 Writer<StringBuffer> writer(buffer);
471 schema.Accept(writer);
472 return buffer.GetString();
479 std::vector<std::pair<std::string, PropertyMap>>& objs,
480 const std::string& title)
482 using namespace rapidjson;
484 Document schema(kObjectType);
485 auto& allocator = schema.GetAllocator();
486 schema.AddMember(StringRef(
"type"), StringRef(
"object"), allocator);
487 schema.AddMember(StringRef(
"title"), StringRef(title.c_str()), allocator);
488 Value oneOf(kArrayType);
490 schema.AddMember(StringRef(
"oneOf"), oneOf, allocator);
493 Writer<StringBuffer> writer(buffer);
494 schema.Accept(writer);
495 return buffer.GetString();
501 const std::string& title)
503 using namespace rapidjson;
505 Document schema(kObjectType);
506 auto& allocator = schema.GetAllocator();
510 Writer<StringBuffer> writer(buffer);
511 schema.Accept(writer);
512 return buffer.GetString();
519 using namespace rapidjson;
521 Document json(kObjectType);
522 auto& allocator = json.GetAllocator();
530 core::make_json_string(prop->name, allocator).Move(),
531 prop->get<
double>(), allocator);
534 if (prop->enums.empty())
537 core::make_json_string(prop->name, allocator).Move(),
538 prop->get<int32_t>(), allocator);
542 auto enumStr = matchEnum(prop->enums, prop->get<int32_t>());
544 core::make_json_string(prop->name, allocator).Move(),
545 core::make_value_string(enumStr, allocator).Move(),
551 core::make_json_string(prop->name, allocator).Move(),
552 core::make_value_string(prop->get<std::string>(), allocator)
558 core::make_json_string(prop->name, allocator).Move(),
559 prop->get<
bool>(), allocator);
562 core::_arrayPropertyToJson<std::array<double, 2>>(json, *prop);
565 core::_arrayPropertyToJson<std::array<int32_t, 2>>(json, *prop);
568 core::_arrayPropertyToJson<std::array<double, 3>>(json, *prop);
571 core::_arrayPropertyToJson<std::array<int32_t, 3>>(json, *prop);
574 core::_arrayPropertyToJson<std::array<double, 4>>(json, *prop);
580 Writer<StringBuffer> writer(buffer);
582 return buffer.GetString();
587 template <
typename T>
588 T
getValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v);
590 double getValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v)
592 return v.GetDouble();
595 int32_t
getValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v)
600 std::string
getValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v)
602 return v.GetString();
605 bool getValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v)
612 template <
typename T>
613 bool isValue(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v);
625 bool isValue<std::string>(
const rapidjson::GenericValue<rapidjson::UTF8<>>& v)
637 template <
typename T,
size_t S>
638 bool get_array(
const rapidjson::Value& v, std::array<T, S>& val)
640 if (!(v.IsArray() && v.Size() == S))
644 for (
const auto& i : v.GetArray())
648 val[j++] = getValue<T>(i);
652 template <
typename T>
657 val = getValue<T>(v);
671 using namespace rapidjson;
674 document.Parse(json.c_str());
678 if (!document.IsObject())
681 for (
const auto& m : document.GetObject())
683 const auto propName = core::snakeCaseToCamelCase(m.name.GetString());
685 const auto trySetProperty = [&](
auto val) {
694 const auto trySetArray = [&](
auto val) {
703 if (trySetProperty(
double(0)))
705 if (trySetProperty(int32_t(0)))
707 if (trySetProperty(std::string(
"")))
709 if (trySetProperty(
bool(
false)))
711 if (trySetArray(std::array<double, 2>{{0, 0}}))
713 if (trySetArray(std::array<int32_t, 2>{{0, 0}}))
715 if (trySetArray(std::array<double, 3>{{0, 0, 0}}))
717 if (trySetArray(std::array<int32_t, 3>{{0, 0, 0}}))
719 if (trySetArray(std::array<double, 4>{{0, 0, 0, 0}}))
void setProperty(const Property &newProperty)
const auto & getProperties() const
void merge(const PropertyMap &input)
bool get_array(const rapidjson::Value &v, std::array< T, S > &val)
T getValue(const rapidjson::GenericValue< rapidjson::UTF8<>> &v)
std::string to_json(const core::PropertyMap &obj)
bool isValue(const rapidjson::GenericValue< rapidjson::UTF8<>> &v)
bool isValue< double >(const rapidjson::GenericValue< rapidjson::UTF8<>> &v)
core::PropertyMap jsonToPropertyMap(const std::string &json)
bool isValue< bool >(const rapidjson::GenericValue< rapidjson::UTF8<>> &v)
bool get_property(const rapidjson::Value &v, T &val)
bool isValue< int >(const rapidjson::GenericValue< rapidjson::UTF8<>> &v)
std::string separatedToCamelCase(const std::string &separated, const char separator)
std::string camelCaseToSeparated(const std::string &camelCase, const char separator)
std::string buildJsonRpcSchemaRequestPropertyMaps(const RpcDescription &desc, const std::vector< std::pair< std::string, PropertyMap >> &objs)
std::string buildJsonRpcSchemaNotifyPropertyMaps(const RpcParameterDescription &desc, const std::vector< std::pair< std::string, PropertyMap >> &objs)
void _addPropertyMapSchema(const PropertyMap &propertyMap, const std::string &title, rapidjson::Document::AllocatorType &allocator, rapidjson::Value &propSchema)
rapidjson::Document _buildJsonRpcSchema(const RpcDescription &desc)
bool from_json(T &obj, const std::string &json, PRE preUpdateFunc=[] {}, POST postUpdateFunc=[] {})
std::string buildJsonSchema(std::vector< std::pair< std::string, PropertyMap >> &objs, const std::string &title)
std::string buildJsonRpcSchemaRequestPropertyMap(const RpcDescription &desc, const PropertyMap &obj)
std::string buildJsonRpcSchemaNotifyPropertyMap(const RpcParameterDescription &desc, const PropertyMap &properties)
void _addPropertyMapOneOfSchema(const std::vector< std::pair< std::string, PropertyMap >> &objs, rapidjson::Document::AllocatorType &allocator, rapidjson::Value &oneOf)