Forráskód Böngészése

fix some problems with json schema export

Kolja Strohm 4 napja
szülő
commit
096435b774
2 módosított fájl, 211 hozzáadás és 173 törlés
  1. 191 173
      DataValidator.cpp
  2. 20 0
      DataValidator.h

+ 191 - 173
DataValidator.cpp

@@ -1322,224 +1322,242 @@ JSON::JSONObject* Framework::Validator::DataValidator::getJsonSchema(
     XML::Element* zConstraint, JSON::JSONObject* zDefs) const
 {
     JSON::JSONObject* result = new JSON::JSONObject();
-    if (zConstraint->hasAttribute("id")
-        && zDefs->hasValue(zConstraint->getAttributeValue("id")))
+    if (zConstraint->hasAttribute("id"))
     {
-        Text jsonRef = Text("#/$defs/") + zConstraint->getAttributeValue("id");
-        result->addValue("$ref", new JSON::JSONString(jsonRef));
+        Text id = zConstraint->getAttributeValue("id");
+        id.ersetzen(" ", "_");
+        if (zDefs->hasValue(id))
+        {
+            Text jsonRef = Text("#/$defs/") + id;
+            result->addValue("$ref", new JSON::JSONString(jsonRef));
+            return result;
+        }
+        zDefs->addValue(id, new JSON::JSONValue()); // avoid endless recursion
+                                                    // for cyclic datastructures
     }
-    else
+    if (zConstraint->getName().istGleich("bool"))
+    {
+        if (zConstraint->hasAttribute("equals"))
+        {
+            JSON::JSONArray* array = new JSON::JSONArray();
+            array->addValue(new JSON::JSONBool(
+                zConstraint->getAttributeValue("equals").istGleich("true")));
+            result->addValue("enum", array);
+        }
+        else
+        {
+            result->addValue("type", new JSON::JSONString("boolean"));
+        }
+    }
+    else if (zConstraint->getName().istGleich("number"))
     {
-        if (zConstraint->getName().istGleich("bool"))
+        if (zConstraint->hasAttribute("equals"))
+        {
+            JSON::JSONArray* array = new JSON::JSONArray();
+            array->addValue(new JSON::JSONNumber(
+                (double)zConstraint->getAttributeValue("equals")));
+            result->addValue("enum", array);
+        }
+        else
         {
-            if (zConstraint->hasAttribute("equals"))
+            result->addValue("type", new JSON::JSONString("number"));
+            if (zConstraint->hasAttribute("lessOrEqual"))
             {
-                JSON::JSONArray* array = new JSON::JSONArray();
-                array->addValue(new JSON::JSONBool(
-                    zConstraint->getAttributeValue("equals").istGleich(
-                        "true")));
-                result->addValue("enum", array);
+                result->addValue("maximum",
+                    new JSON::JSONNumber(
+                        (double)zConstraint->getAttributeValue("lessOrEqual")));
             }
-            else
+            if (zConstraint->hasAttribute("greaterOrEqual"))
             {
-                result->addValue("type", new JSON::JSONString("boolean"));
+                result->addValue("minimum",
+                    new JSON::JSONNumber((double)zConstraint->getAttributeValue(
+                        "greaterOrEqual")));
             }
-        }
-        else if (zConstraint->getName().istGleich("number"))
-        {
-            if (zConstraint->hasAttribute("equals"))
+            if (zConstraint->hasAttribute("less"))
             {
-                JSON::JSONArray* array = new JSON::JSONArray();
-                array->addValue(new JSON::JSONNumber(
-                    (double)zConstraint->getAttributeValue("equals")));
-                result->addValue("enum", array);
+                result->addValue("exclusiveMaximum",
+                    new JSON::JSONNumber(
+                        (double)zConstraint->getAttributeValue("less")));
             }
-            else
+            if (zConstraint->hasAttribute("greater"))
             {
-                result->addValue("type", new JSON::JSONString("number"));
-                if (zConstraint->hasAttribute("lessOrEqual"))
-                {
-                    result->addValue("maximum",
-                        new JSON::JSONNumber(
-                            (double)zConstraint->getAttributeValue(
-                                "lessOrEqual")));
-                }
-                if (zConstraint->hasAttribute("greaterOrEqual"))
-                {
-                    result->addValue("minimum",
-                        new JSON::JSONNumber(
-                            (double)zConstraint->getAttributeValue(
-                                "greaterOrEqual")));
-                }
-                if (zConstraint->hasAttribute("less"))
-                {
-                    result->addValue("exclusiveMaximum",
-                        new JSON::JSONNumber(
-                            (double)zConstraint->getAttributeValue("less")));
-                }
-                if (zConstraint->hasAttribute("greater"))
-                {
-                    result->addValue("exclusiveMinimum",
-                        new JSON::JSONNumber(
-                            (double)zConstraint->getAttributeValue("greater")));
-                }
+                result->addValue("exclusiveMinimum",
+                    new JSON::JSONNumber(
+                        (double)zConstraint->getAttributeValue("greater")));
             }
         }
-        else if (zConstraint->getName().istGleich("string"))
+    }
+    else if (zConstraint->getName().istGleich("string"))
+    {
+        if (zConstraint->hasAttribute("equals"))
+        {
+            JSON::JSONArray* array = new JSON::JSONArray();
+            array->addValue(
+                new JSON::JSONString(zConstraint->getAttributeValue("equals")));
+            result->addValue("enum", array);
+        }
+        else if (zConstraint->hasAttribute("oneOf"))
+        {
+            JSON::JSONArray* array = JSON::Parser::getValue(
+                zConstraint->getAttributeValue("oneOf"))
+                                         ->asArray();
+            result->addValue("enum", array);
+        }
+        else
         {
-            if (zConstraint->hasAttribute("equals"))
+            result->addValue("type", new JSON::JSONString("string"));
+            if (zConstraint->hasAttribute("contains"))
             {
-                JSON::JSONArray* array = new JSON::JSONArray();
-                array->addValue(new JSON::JSONString(
-                    zConstraint->getAttributeValue("equals")));
-                result->addValue("enum", array);
+                result->addValue("pattern",
+                    new JSON::JSONString(
+                        Text(".*")
+                        + Regex::quote(
+                            zConstraint->getAttributeValue("contains"))
+                        + ".*"));
             }
-            else if (zConstraint->hasAttribute("oneOf"))
+            if (zConstraint->hasAttribute("startsWith"))
             {
-                JSON::JSONArray* array = JSON::Parser::getValue(
-                    zConstraint->getAttributeValue("oneOf"))
-                                             ->asArray();
-                result->addValue("enum", array);
+                result->addValue("pattern",
+                    new JSON::JSONString(
+                        Text("^")
+                        + Regex::quote(
+                            zConstraint->getAttributeValue("startsWith"))
+                        + ".*"));
             }
-            else
+            if (zConstraint->hasAttribute("endsWith"))
             {
-                result->addValue("type", new JSON::JSONString("string"));
-                if (zConstraint->hasAttribute("contains"))
-                {
-                    result->addValue("pattern",
-                        new JSON::JSONString(
-                            Text(".*")
-                            + Regex::quote(
-                                zConstraint->getAttributeValue("contains"))
-                            + ".*"));
-                }
-                if (zConstraint->hasAttribute("startsWith"))
-                {
-                    result->addValue("pattern",
-                        new JSON::JSONString(
-                            Text("^")
-                            + Regex::quote(
-                                zConstraint->getAttributeValue("startsWith"))
-                            + ".*"));
-                }
-                if (zConstraint->hasAttribute("endsWith"))
-                {
-                    result->addValue("pattern",
-                        new JSON::JSONString(
-                            Text(".*")
-                            + Regex::quote(
-                                zConstraint->getAttributeValue("endsWith"))
-                            + "$"));
-                }
+                result->addValue("pattern",
+                    new JSON::JSONString(
+                        Text(".*")
+                        + Regex::quote(
+                            zConstraint->getAttributeValue("endsWith"))
+                        + "$"));
             }
         }
-        else if (zConstraint->getName().istGleich("ref"))
+    }
+    else if (zConstraint->getName().istGleich("ref"))
+    {
+        Text id = zConstraint->getAttributeValue("ref");
+        XML::Element* e = typeConstraints->z(id, id.getLength());
+        id.ersetzen(" ", "_");
+        if (!zDefs->hasValue(id))
         {
-            Text id = zConstraint->getAttributeValue("ref");
-            XML::Element* e = typeConstraints->z(id, id.getLength());
-            if (!zDefs->hasValue(id))
+            JSON::JSONObject* def = getJsonSchema(e, zDefs);
+            if (!def->hasValue(id))
             {
-                zDefs->addValue(
-                    id, new JSON::JSONValue()); // avoid endless recursion for
-                                                // cyclic datastructures
-                JSON::JSONObject* def = getJsonSchema(e, zDefs);
-                zDefs->removeValue(id);
                 zDefs->addValue(id, def);
             }
-            Text jsonRef = Text("#/$defs/") + id;
-            result->addValue("$ref", new JSON::JSONString(jsonRef));
-        }
-        else if (zConstraint->getName().istGleich("object"))
-        {
-            result->addValue("type", new JSON::JSONString("object"));
-            result->addValue("additionalProperties",
-                new JSON::JSONBool(
-                    zConstraint->getAttributeValue("allowAdditionalAttributes")
-                        .istGleich("true")));
-            JSON::JSONObject* properties = new JSON::JSONObject();
-            JSON::JSONArray* required = new JSON::JSONArray();
-            for (XML::Element* e : zConstraint->selectChildren())
+            else
             {
-                JSON::JSONObject* prop = getJsonSchema(e->zChild(0), zDefs);
-                properties->addValue(e->getAttributeValue("name"), prop);
-                if (!e->getAttributeValue("optional").istGleich("true"))
-                {
-                    required->addValue(
-                        new JSON::JSONString(e->getAttributeValue("name")));
-                }
+                // def was already added by a child
+                def->release();
             }
-            result->addValue("properties", properties);
-            result->addValue("required", required);
         }
-        else if (zConstraint->getName().istGleich("array"))
+        Text jsonRef = Text("#/$defs/") + id;
+        result->addValue("$ref", new JSON::JSONString(jsonRef));
+    }
+    else if (zConstraint->getName().istGleich("object"))
+    {
+        result->addValue("type", new JSON::JSONString("object"));
+        result->addValue("additionalProperties",
+            new JSON::JSONBool(
+                zConstraint->getAttributeValue("allowAdditionalAttributes")
+                    .istGleich("true")));
+        JSON::JSONObject* properties = new JSON::JSONObject();
+        JSON::JSONArray* required = new JSON::JSONArray();
+        for (XML::Element* e : zConstraint->selectChildren())
         {
-            result->addValue("type", new JSON::JSONString("array"));
-            JSON::JSONObject* items = new JSON::JSONObject();
+            JSON::JSONObject* prop = new JSON::JSONObject();
             JSON::JSONArray* oneOf = new JSON::JSONArray();
-            for (XML::Element* e : zConstraint->selectChildren())
+            bool isRequired = true;
+            for (XML::Element* child : e->selectChildren())
             {
-                oneOf->addValue(getJsonSchema(e, zDefs));
+                oneOf->addValue(getJsonSchema(child, zDefs));
+                isRequired
+                    &= !child->getAttributeValue("optional").istGleich("true")
+                    && !child->hasAttribute("default");
             }
-            items->addValue("oneOf", oneOf);
-            result->addValue("items", items);
-        }
-        else if (zConstraint->getName().istGleich("oneOf"))
-        {
-            JSON::JSONArray* oneOf = new JSON::JSONArray();
-            for (XML::Element* e : zConstraint->selectChildren())
+            prop->addValue("oneOf", oneOf);
+            properties->addValue(e->getAttributeValue("name"), prop);
+            if (isRequired)
             {
-                oneOf->addValue(getJsonSchema(e, zDefs));
+                required->addValue(
+                    new JSON::JSONString(e->getAttributeValue("name")));
             }
-            result->addValue("oneOf", oneOf);
         }
-        if (zConstraint->hasAttribute("nullable")
-            && zConstraint->getAttributeValue("nullable").istGleich("true"))
+        result->addValue("properties", properties);
+        result->addValue("required", required);
+    }
+    else if (zConstraint->getName().istGleich("array"))
+    {
+        result->addValue("type", new JSON::JSONString("array"));
+        JSON::JSONObject* items = new JSON::JSONObject();
+        JSON::JSONArray* oneOf = new JSON::JSONArray();
+        for (XML::Element* e : zConstraint->selectChildren())
+        {
+            oneOf->addValue(getJsonSchema(e, zDefs));
+        }
+        items->addValue("oneOf", oneOf);
+        result->addValue("items", items);
+    }
+    else if (zConstraint->getName().istGleich("oneOf"))
+    {
+        JSON::JSONArray* oneOf = new JSON::JSONArray();
+        for (XML::Element* e : zConstraint->selectChildren())
+        {
+            oneOf->addValue(getJsonSchema(e, zDefs));
+        }
+        result->addValue("oneOf", oneOf);
+    }
+    if (zConstraint->hasAttribute("nullable")
+        && zConstraint->getAttributeValue("nullable").istGleich("true"))
+    {
+        if (!result->hasValue("type"))
         {
-            if (!result->hasValue("type"))
+            if (result->hasValue("enum"))
             {
-                if (result->hasValue("enum"))
-                {
-                    result->zValue("enum")->asArray()->addValue(
-                        new JSON::JSONValue());
-                }
-                else
-                {
-                    JSON::JSONObject* oneOf = new JSON::JSONObject();
-                    JSON::JSONArray* array = new JSON::JSONArray();
-                    array->addValue(result);
-                    JSON::JSONObject* nullType = new JSON::JSONObject();
-                    nullType->addValue("type", new JSON::JSONString("null"));
-                    array->addValue(nullType);
-                    oneOf->addValue("oneOf", array);
-                    result = oneOf;
-                }
+                result->zValue("enum")->asArray()->addValue(
+                    new JSON::JSONValue());
             }
             else
             {
-                if (result->zValue("Type")->getType() == AbstractType::ARRAY)
-                {
-                    result->zValue("Type")->asArray()->addValue(
-                        new JSON::JSONString("null"));
-                }
-                else
-                {
-                    JSON::JSONArray* array = new JSON::JSONArray();
-                    array->addValue(result->getValue("Type"));
-                    array->addValue(new JSON::JSONString("null"));
-                    result->removeValue("type");
-                    result->addValue("type", array);
-                }
+                JSON::JSONObject* oneOf = new JSON::JSONObject();
+                JSON::JSONArray* array = new JSON::JSONArray();
+                array->addValue(result);
+                JSON::JSONObject* nullType = new JSON::JSONObject();
+                nullType->addValue("type", new JSON::JSONString("null"));
+                array->addValue(nullType);
+                oneOf->addValue("oneOf", array);
+                result = oneOf;
             }
         }
-        if (zConstraint->hasAttribute("id"))
+        else
         {
-            zDefs->addValue(zConstraint->getAttributeValue("id"), result);
-            result = new JSON::JSONObject();
-            Text jsonRef
-                = Text("#/$defs/") + zConstraint->getAttributeValue("id");
-            result->addValue("$ref", new JSON::JSONString(jsonRef));
+            if (result->zValue("type")->getType() == AbstractType::ARRAY)
+            {
+                result->zValue("type")->asArray()->addValue(
+                    new JSON::JSONString("null"));
+            }
+            else
+            {
+                JSON::JSONArray* array = new JSON::JSONArray();
+                array->addValue(result->getValue("type"));
+                array->addValue(new JSON::JSONString("null"));
+                result->removeValue("type");
+                result->addValue("type", array);
+            }
         }
     }
+    if (zConstraint->hasAttribute("id"))
+    {
+        Text id = zConstraint->getAttributeValue("id");
+        id.ersetzen(" ", "_");
+        zDefs->removeValue(id);
+        zDefs->addValue(id, result);
+        result = new JSON::JSONObject();
+        Text jsonRef = Text("#/$defs/") + id;
+        result->addValue("$ref", new JSON::JSONString(jsonRef));
+    }
     return result;
 }
 

+ 20 - 0
DataValidator.h

@@ -660,6 +660,26 @@ namespace Framework
                 return this;
             }
 
+            ObjectValidationBuilder<T>* withRequiredAttribute(Text name,
+                DataValidator* validator,
+                bool canBeNull,
+                bool optional)
+            {
+                if (!element.selectChildsByAttribute("name", name).exists())
+                {
+                    XML::Element* attr = new XML::Element("<value></value>");
+                    attr->setAttribute("name", name);
+                    element.addChild(attr);
+                }
+                XML::Element* element = validator->zConstraints()->dublicate();
+                element->setAttribute("nullable", canBeNull ? "true" : "false");
+                element->setAttribute("optional", optional ? "true" : "false");
+                this->element.selectChildsByAttribute("name", name)
+                    .addChild(element);
+                validator->release();
+                return this;
+            }
+
             ObjectValidationBuilder<T>* withDefault(JSON::JSONObject* obj)
             {
                 element.setAttribute("default", obj->toString());