1 /******************************************************************
\r
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 ******************************************************************/
\r
21 #include "JsonSchema.h"
\r
22 using namespace std;
\r
27 void JsonSchema::readJson()
\r
32 cJSON *jsonId = cJSON_GetObjectItem(m_cjson, "id");
\r
35 m_id = jsonId->valuestring;
\r
37 cJSON *jsonSchema = cJSON_GetObjectItem(m_cjson, "$schema");
\r
40 m_schema = jsonSchema->valuestring;
\r
42 cJSON *jsonTitle = cJSON_GetObjectItem(m_cjson, "title");
\r
45 m_title = jsonTitle->valuestring;
\r
47 cJSON *jsonType = cJSON_GetObjectItem(m_cjson, "type");
\r
50 m_type = jsonType->valuestring;
\r
52 cJSON *jsonDescription = cJSON_GetObjectItem(m_cjson, "description");
\r
53 if (jsonDescription)
\r
55 m_description = jsonDescription->valuestring;
\r
57 cJSON *jsonDefinitions = cJSON_GetObjectItem(m_cjson, "definitions");
\r
58 if (jsonDefinitions)
\r
60 cJSON *childDefinitions = jsonDefinitions->child;
\r
61 while (childDefinitions)
\r
63 std::string defName = childDefinitions->string;
\r
64 addDefinition(defName, readDef(childDefinitions, defName));
\r
65 childDefinitions = childDefinitions->next;
\r
68 cJSON *jsonProperties = cJSON_GetObjectItem(m_cjson, "properties");
\r
71 cJSON *childProperties = jsonProperties->child;
\r
72 while (childProperties)
\r
74 std::string attName = childProperties->string;
\r
75 addProperty(attName, readProp(childProperties, attName));
\r
76 childProperties = childProperties->next;
\r
79 if (m_type == "array")
\r
81 cJSON *jsonItems = cJSON_GetObjectItem(m_cjson, "items");
\r
84 if (jsonItems->type == 5)
\r
86 int item_size = cJSON_GetArraySize(jsonItems);
\r
90 cJSON *item = cJSON_GetArrayItem(jsonItems, item_index);
\r
91 setItem(readItems(item));
\r
93 while ( ++item_index < item_size);
\r
97 setItem(readItems(jsonItems));
\r
101 cJSON *jsonAdditionalProperties = cJSON_GetObjectItem(m_cjson, "additionalProperties");
\r
102 if (jsonAdditionalProperties)
\r
103 m_additionalProperties = jsonAdditionalProperties->type;
\r
105 m_additionalProperties = cJSON_True;
\r
107 cJSON *jsonReference = cJSON_GetObjectItem(m_cjson, "$ref");
\r
110 readJsonRef(jsonReference);
\r
112 cJSON *jsonAllOf = cJSON_GetObjectItem(m_cjson, "allOf");
\r
115 readAllOf(jsonAllOf);
\r
117 cJSON *jsonRequiredValues = cJSON_GetObjectItem(m_cjson, "required");
\r
118 if (jsonRequiredValues)
\r
120 int size = cJSON_GetArraySize(jsonRequiredValues);
\r
124 setRequiredValue(cJSON_GetArrayItem(jsonRequiredValues, index)->valuestring);
\r
126 while ( ++index < size);
\r
130 DefinitionsPtr JsonSchema::readDef(cJSON *childDefinitions, const std::string &defName)
\r
132 DefinitionsPtr definition = std::make_shared<Definitions>(defName);
\r
134 cJSON *defType = cJSON_GetObjectItem(childDefinitions, "type");
\r
137 std::string type = defType->valuestring;
\r
138 definition->setType(type);
\r
140 cJSON *defProperties = cJSON_GetObjectItem(childDefinitions, "properties");
\r
143 cJSON *childProperties = defProperties->child;
\r
144 while (childProperties)
\r
146 std::string attName = childProperties->string;
\r
147 definition->addProperty(attName, readProp(childProperties, attName));
\r
148 childProperties = childProperties->next;
\r
151 cJSON *defRequiredValues = cJSON_GetObjectItem(childDefinitions, "required");
\r
152 if (defRequiredValues)
\r
154 int size = cJSON_GetArraySize(defRequiredValues);
\r
158 definition->setRequiredValue(cJSON_GetArrayItem(defRequiredValues, index)->valuestring);
\r
160 while ( ++index < size);
\r
162 cJSON *defReference = cJSON_GetObjectItem(childDefinitions, "$ref");
\r
165 readDefRef(defReference, definition);
\r
167 cJSON *defAllOf = cJSON_GetObjectItem(childDefinitions, "allOf");
\r
170 readDefAllOf(defAllOf, definition);
\r
175 PropertiesPtr JsonSchema::readProp(cJSON *childProperties, const std::string &attName )
\r
177 PropertiesPtr property = std::make_shared<Properties>(attName);
\r
179 cJSON *propertyUpdateFrequency = cJSON_GetObjectItem(childProperties, "update_frequency");
\r
180 if (propertyUpdateFrequency)
\r
182 property->setUpdateFrequencyTime(propertyUpdateFrequency->valueint);
\r
184 cJSON *propertyDescription = cJSON_GetObjectItem(childProperties, "description");
\r
185 if (propertyDescription)
\r
187 property->setDescription(propertyDescription->valuestring);
\r
189 cJSON *propertyType = cJSON_GetObjectItem(childProperties, "type");
\r
192 std::string attType;
\r
193 if (propertyType->type == 4)
\r
195 attType = propertyType->valuestring;
\r
196 property->setType(attType);
\r
198 else if (propertyType->type == 5)
\r
200 attType = cJSON_GetArrayItem(propertyType, 0)->valuestring;
\r
201 property->setType(attType);
\r
203 readValues(childProperties, property, attType);
\r
205 cJSON *defaultValue = cJSON_GetObjectItem(childProperties, "default");
\r
208 if (defaultValue->type == 4)
\r
210 property->setValue((std::string)defaultValue->valuestring);
\r
212 else if (defaultValue->type == 3)
\r
214 if (property->getType() == "number")
\r
215 property->setValue((double)defaultValue->valuedouble);
\r
217 property->setValue((int)defaultValue->valueint );
\r
219 else if (defaultValue->type == 1)
\r
221 property->setValue((bool)true);
\r
223 else if (defaultValue->type == 0)
\r
225 property->setValue((bool)false);
\r
229 cJSON *allowedvalues = cJSON_GetObjectItem(childProperties, "enum");
\r
232 if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 4)
\r
234 int size = cJSON_GetArraySize(allowedvalues);
\r
236 std::vector<std::string> allwdValues;
\r
239 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuestring);
\r
241 while ( ++idx < size);
\r
242 property->setAllowedValues(allwdValues);
\r
244 else if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 3)
\r
246 int size = cJSON_GetArraySize(allowedvalues);
\r
248 if (property->getType() == "number")
\r
250 std::vector<double> allwdValues;
\r
253 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuedouble);
\r
255 while ( ++idx < size);
\r
256 property->setAllowedValues(allwdValues);
\r
260 std::vector<int> allwdValues;
\r
263 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valueint);
\r
265 while ( ++idx < size);
\r
266 property->setAllowedValues(allwdValues);
\r
269 else if (((cJSON_GetArrayItem(allowedvalues, 0)->type) == 1)
\r
270 || ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 0))
\r
272 int size = cJSON_GetArraySize(allowedvalues);
\r
274 std::vector<bool> allwdValues;
\r
277 if (cJSON_GetArrayItem(allowedvalues, idx)->type)
\r
278 allwdValues.push_back(true);
\r
280 allwdValues.push_back(false);
\r
282 while ( ++idx < size);
\r
283 property->setAllowedValues(allwdValues);
\r
289 void JsonSchema::readValues(cJSON *childProperties, PropertiesPtr property ,
\r
290 const std::string &attType)
\r
292 if (attType == "string")
\r
294 readString(childProperties, property);
\r
296 else if (attType == "integer")
\r
298 readNumber(childProperties, property);
\r
300 else if (attType == "array")
\r
302 readArray(childProperties, property);
\r
304 else if (attType == "number")
\r
306 readNumber(childProperties, property);
\r
310 void JsonSchema::readString(cJSON *childProperties, PropertiesPtr property)
\r
312 cJSON *stringMax = cJSON_GetObjectItem(childProperties, "maxLength");
\r
315 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
318 if (exclusiveMax->type == cJSON_True)
\r
319 property->setMax (--(stringMax->valueint));
\r
321 property->setMax(stringMax->valueint);
\r
324 property->setMax(stringMax->valueint);
\r
326 cJSON *stringMin = cJSON_GetObjectItem(childProperties, "minLength");
\r
329 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
332 if (exclusiveMin->type == cJSON_True)
\r
333 property->setMin( ++(stringMin->valueint));
\r
335 property->setMin(stringMin->valueint);
\r
338 property->setMin(stringMin->valueint);
\r
340 cJSON *stringFormat = cJSON_GetObjectItem(childProperties, "format");
\r
343 property->setFormat(stringFormat->valuestring);
\r
345 cJSON *stringPattern = cJSON_GetObjectItem(childProperties, "pattern");
\r
348 property->setPattern(stringPattern->valuestring);
\r
352 void JsonSchema::readArray(cJSON *childProperties, PropertiesPtr property)
\r
354 cJSON *itemValues = cJSON_GetObjectItem(childProperties, "items");
\r
357 if (itemValues->type == 5)
\r
359 int item_size = cJSON_GetArraySize(itemValues);
\r
360 int item_index = 0;
\r
363 cJSON *item = cJSON_GetArrayItem(itemValues, item_index);
\r
364 property->setItem(readItems(item));
\r
366 while ( ++item_index < item_size);
\r
370 property->setItem(readItems(itemValues));
\r
373 cJSON *itemsMax = cJSON_GetObjectItem(childProperties, "maxItems");
\r
376 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
379 if (exclusiveMax->type == cJSON_True)
\r
380 property->setMax( --(itemsMax->valueint));
\r
382 property->setMax(itemsMax->valueint);
\r
385 property->setMax(itemsMax->valueint);
\r
387 cJSON *itemsMin = cJSON_GetObjectItem(childProperties, "minLength");
\r
390 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
393 if (exclusiveMin->type == cJSON_True)
\r
394 property->setMin( ++(itemsMin->valueint));
\r
396 property->setMin(itemsMin->valueint);
\r
399 property->setMin(itemsMin->valueint);
\r
401 cJSON *uniqueItems = cJSON_GetObjectItem(childProperties, "uniqueItems");
\r
404 property->setUnique(uniqueItems->type);
\r
408 property->setUnique(cJSON_True);
\r
410 cJSON *additionalItems = cJSON_GetObjectItem(childProperties, "additionalItems");
\r
411 if (additionalItems)
\r
413 property->setAdditionalItems(additionalItems->type);
\r
417 property->setAdditionalItems(cJSON_True);
\r
421 void JsonSchema::readNumber(cJSON *childProperties, PropertiesPtr property)
\r
423 cJSON *Max = cJSON_GetObjectItem(childProperties, "maximum");
\r
426 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
429 if (exclusiveMax->type == cJSON_True)
\r
430 property->setMax( --(Max->valueint));
\r
432 property->setMax(Max->valueint);
\r
435 property->setMax(Max->valueint);
\r
437 cJSON *Min = cJSON_GetObjectItem(childProperties, "minimum");
\r
440 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
443 if (exclusiveMin->type == cJSON_True)
\r
444 property->setMin( ++(Min->valueint));
\r
446 property->setMin(Min->valueint);
\r
449 property->setMin(Min->valueint);
\r
451 cJSON *multipleOf = cJSON_GetObjectItem(childProperties, "multipleOf");
\r
454 property->setMultipleOf(multipleOf->valueint);
\r
458 DefinitionsPtr JsonSchema::readRef(std::string m_ref)
\r
460 std::string delimiter1 = "#";
\r
461 std::string delimiter2 = "/";
\r
462 std::string fileName;
\r
463 if (! m_ref.empty())
\r
465 std::size_t pos = m_ref.find(delimiter1);
\r
466 if ( (pos = m_ref.find(delimiter1)) != std::string::npos)
\r
468 fileName = m_ref.substr(0, pos);
\r
469 m_ref.erase(0, pos);
\r
471 m_ref.erase(0, delimiter1 .length());
\r
472 std::string defName;
\r
474 if (! m_ref.empty())
\r
476 m_ref.erase(0, delimiter2 .length());
\r
477 std::string keyName;
\r
478 if ( (pos = m_ref.find(delimiter2)) != std::string::npos)
\r
480 keyName = m_ref.substr(0, pos);
\r
481 m_ref.erase(0, pos + delimiter2.length());
\r
482 if (keyName == "definitions")
\r
484 if ( (pos = m_ref.find(delimiter2)) != std::string::npos)
\r
486 defName = m_ref.substr(0, pos);
\r
488 else if (! m_ref.empty())
\r
495 if (!fileName.empty())
\r
497 if (!(defName.empty()))
\r
499 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
500 JsonSchemaPtr Refparser = std::make_shared<JsonSchema>(m_json, m_includeResolver);
\r
501 DefinitionsPtr definition = Refparser->getDefinition(defName);
\r
502 if (definition == nullptr)
\r
503 throw JsonException("Definition Name Incorrect");
\r
509 if (!(defName.empty()))
\r
511 if (getDefinition(defName) == nullptr)
\r
512 throw JsonException("Definition Name Incorrect");
\r
513 return getDefinition(defName);
\r
517 throw JsonException("Definition Name Empty");
\r
520 void JsonSchema::readAllOf(cJSON *allofValues)
\r
522 int size = cJSON_GetArraySize(allofValues);
\r
526 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
527 cJSON *jsonReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
530 readJsonRef(jsonReference );
\r
532 cJSON *jsonRequiredValues = cJSON_GetObjectItem(childAllOf, "required");
\r
533 if (jsonRequiredValues)
\r
535 int len = cJSON_GetArraySize(jsonRequiredValues);
\r
539 setRequiredValue(cJSON_GetArrayItem(jsonRequiredValues, idx)->valuestring);
\r
541 while ( ++idx < len);
\r
544 while ( ++index < size);
\r
546 void JsonSchema::readJsonRef(cJSON *jsonReference)
\r
548 std::string m_ref = jsonReference->valuestring;
\r
549 std::map<std::string, PropertiesPtr > properties;
\r
550 std::vector<std::string> required;
\r
552 std::string web = "http://";
\r
553 std::string delimiter = "#";
\r
554 std::size_t pos = m_ref.find(web);
\r
556 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
558 pos = m_ref.find(delimiter);
\r
559 if ( pos == (m_ref.length() - 1) )
\r
561 std::string fileName = m_ref.substr(0, pos);
\r
562 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
563 JsonSchemaPtr Refparser = std::make_shared<JsonSchema>(m_json, m_includeResolver);
\r
565 properties = Refparser->getProperties();
\r
566 required = Refparser->getRequiredValues();
\r
570 DefinitionsPtr definition = readRef(m_ref);
\r
571 properties = definition->getProperties();
\r
572 required = definition->getRequiredValues();
\r
574 for ( auto it : properties)
\r
576 std:: string name = it.first;
\r
577 addProperty(name, it.second);
\r
579 for (auto it : required )
\r
581 setRequiredValue(it);
\r
586 void JsonSchema::readDefAllOf(cJSON *allofValues, DefinitionsPtr definition)
\r
588 int size = cJSON_GetArraySize(allofValues);
\r
592 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
593 cJSON *defReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
596 readDefRef(defReference , definition);
\r
598 cJSON *defRequiredValues = cJSON_GetObjectItem(allofValues, "required");
\r
599 if (defRequiredValues)
\r
601 int len = cJSON_GetArraySize(defRequiredValues);
\r
605 definition->setRequiredValue(cJSON_GetArrayItem(defRequiredValues, idx)->valuestring);
\r
607 while ( ++idx < len);
\r
610 while ( ++index < size);
\r
612 void JsonSchema::readDefRef(cJSON *defReference, DefinitionsPtr definition)
\r
614 std::string m_ref = defReference->valuestring;
\r
615 std::map<std::string, PropertiesPtr > properties;
\r
616 std::vector<std::string> required;
\r
619 std::string web = "http://";
\r
620 std::string delimiter = "#";
\r
621 std::size_t pos = m_ref.find(web);
\r
623 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
625 pos = m_ref.find(delimiter);
\r
626 if ( pos == (m_ref.length() - 1) )
\r
628 std::string fileName = m_ref.substr(0, pos);
\r
629 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
630 JsonSchemaPtr Refparser = std::make_shared<JsonSchema>(m_json, m_includeResolver);
\r
632 properties = Refparser->getProperties();
\r
633 required = Refparser->getRequiredValues();
\r
634 type = Refparser->getType();
\r
638 DefinitionsPtr definitionRef = readRef(m_ref);
\r
639 properties = definitionRef->getProperties();
\r
640 required = definitionRef->getRequiredValues();
\r
641 type = definitionRef->getType();
\r
643 for (auto it : properties)
\r
645 definition->addProperty(it.first, it.second);
\r
647 for ( auto it : required)
\r
649 definition->setRequiredValue(it);
\r
651 definition->setType(type);
\r
654 ItemsPtr JsonSchema::readItems(cJSON *item)
\r
656 ItemsPtr newItem = std::make_shared<Items>();
\r
657 cJSON *itemType = cJSON_GetObjectItem(item, "type");
\r
660 std::string type = itemType->valuestring;
\r
661 newItem->setType(type);
\r
664 cJSON *itemProperties = cJSON_GetObjectItem(item, "properties");
\r
665 if (itemProperties)
\r
667 cJSON *childProperties = itemProperties->child;
\r
668 while (childProperties)
\r
670 std::string attName = childProperties->string;
\r
672 newItem->addProperty(attName, readProp(childProperties, attName));
\r
673 childProperties = childProperties->next;
\r
677 cJSON *allowedvalues = cJSON_GetObjectItem(item, "enum");
\r
680 if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 4)
\r
682 int size = cJSON_GetArraySize(allowedvalues);
\r
684 std::vector<std::string> allwdValues;
\r
687 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuestring);
\r
689 while ( ++idx < size);
\r
690 newItem->setAllowedValues(allwdValues);
\r
692 else if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 3)
\r
694 int size = cJSON_GetArraySize(allowedvalues);
\r
696 if (newItem->getType() == "number")
\r
698 std::vector<double> allwdValues;
\r
701 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuedouble);
\r
703 while ( ++idx < size);
\r
704 newItem->setAllowedValues(allwdValues);
\r
708 std::vector<int> allwdValues;
\r
711 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valueint);
\r
713 while ( ++idx < size);
\r
714 newItem->setAllowedValues(allwdValues);
\r
717 else if (((cJSON_GetArrayItem(allowedvalues, 0)->type) == 1)
\r
718 || ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 0))
\r
720 int size = cJSON_GetArraySize(allowedvalues);
\r
722 std::vector<bool> allwdValues;
\r
725 if (cJSON_GetArrayItem(allowedvalues, idx)->type)
\r
726 allwdValues.push_back(true);
\r
728 allwdValues.push_back(false);
\r
730 while ( ++idx < size);
\r
731 newItem->setAllowedValues(allwdValues);
\r
734 cJSON *itemRequiredValues = cJSON_GetObjectItem(item, "required");
\r
735 if (itemRequiredValues)
\r
737 int size = cJSON_GetArraySize(itemRequiredValues);
\r
741 newItem->setRequiredValue(cJSON_GetArrayItem(itemRequiredValues, index)->valuestring);
\r
743 while ( ++index < size);
\r
745 cJSON *itemReference = cJSON_GetObjectItem(item, "$ref");
\r
748 readItemRef(itemReference , newItem);
\r
750 cJSON *itemAllOf = cJSON_GetObjectItem(item, "allOf");
\r
753 readItemAllOf(itemAllOf , newItem);
\r
758 void JsonSchema::readItemRef(cJSON *itemReference, ItemsPtr item)
\r
760 std::string m_ref = itemReference->valuestring;
\r
761 std::map<std::string, PropertiesPtr > properties;
\r
762 std::vector<std::string> required;
\r
765 std::string web = "http://";
\r
766 std::string delimiter = "#";
\r
767 std::size_t pos = m_ref.find(web);
\r
769 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
771 pos = m_ref.find(delimiter);
\r
772 if ( pos == (m_ref.length() - 1 ) )
\r
774 std::string fileName = m_ref.substr(0, pos);
\r
775 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
776 JsonSchemaPtr Refparser = std::make_shared<JsonSchema>(m_json, m_includeResolver);
\r
778 properties = Refparser->getProperties();
\r
779 required = Refparser->getRequiredValues();
\r
780 type = Refparser->getType();
\r
784 DefinitionsPtr definitionRef = readRef(m_ref);
\r
785 properties = definitionRef->getProperties();
\r
786 required = definitionRef->getRequiredValues();
\r
787 type = definitionRef->getType();
\r
789 for ( auto it : properties)
\r
791 std:: string name = it.first;
\r
792 item->addProperty(name, it.second);
\r
794 for ( auto it : required)
\r
796 item->setRequiredValue(it);
\r
798 item->setType(type);
\r
802 void JsonSchema::readItemAllOf(cJSON *allofValues, ItemsPtr item)
\r
804 int size = cJSON_GetArraySize(allofValues);
\r
808 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
809 cJSON *itemReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
812 readItemRef(itemReference, item);
\r
814 cJSON *itemRequiredValues = cJSON_GetObjectItem(allofValues, "required");
\r
815 if (itemRequiredValues)
\r
817 int len = cJSON_GetArraySize(itemRequiredValues);
\r
821 item->setRequiredValue(cJSON_GetArrayItem(itemRequiredValues, idx)->valuestring);
\r
823 while ( ++idx < len);
\r
826 while ( ++index < size);
\r