2017-07-30 13:32:10 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// QT include
|
|
|
|
#include <QString>
|
|
|
|
#include <QStringList>
|
|
|
|
#include <QJsonObject>
|
|
|
|
#include <QJsonValue>
|
|
|
|
#include <QJsonArray>
|
|
|
|
|
|
|
|
class QJsonUtils
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
static void modify(QJsonObject& value, QStringList path, const QJsonValue& newValue = QJsonValue::Null, QString propertyName = "")
|
|
|
|
{
|
|
|
|
QJsonObject result;
|
|
|
|
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
if (path.first() == "[root]")
|
|
|
|
path.removeFirst();
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
for (QStringList::iterator it = path.begin(); it != path.end(); ++it)
|
|
|
|
{
|
|
|
|
QString current = *it;
|
|
|
|
if (current.left(1) == ".")
|
|
|
|
*it = current.mid(1, current.size()-1);
|
|
|
|
}
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (!value.isEmpty())
|
|
|
|
modifyValue(value, result, path, newValue, propertyName);
|
|
|
|
else if (newValue != QJsonValue::Null && !propertyName.isEmpty())
|
|
|
|
result[propertyName] = newValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
value = result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static QJsonValue create(QJsonValue schema, bool ignoreRequired = false)
|
|
|
|
{
|
|
|
|
return createValue(schema, ignoreRequired);
|
|
|
|
}
|
|
|
|
|
2020-03-27 23:13:58 +01:00
|
|
|
static QString getDefaultValue(const QJsonValue & value)
|
|
|
|
{
|
|
|
|
QString ret;
|
|
|
|
switch (value.type())
|
|
|
|
{
|
|
|
|
case QJsonValue::Array:
|
|
|
|
{
|
2020-11-14 17:58:56 +01:00
|
|
|
for (const QJsonValueRef v : value.toArray())
|
2020-03-27 23:13:58 +01:00
|
|
|
{
|
|
|
|
ret = getDefaultValue(v);
|
|
|
|
if (!ret.isEmpty())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QJsonValue::Object:
|
|
|
|
ret = getDefaultValue(value.toObject().find("default").value());
|
|
|
|
break;
|
|
|
|
case QJsonValue::Bool:
|
|
|
|
return value.toBool() ? "True" : "False";
|
|
|
|
case QJsonValue::Double:
|
|
|
|
return QString::number(value.toDouble());
|
|
|
|
case QJsonValue::String:
|
|
|
|
return value.toString();
|
|
|
|
case QJsonValue::Null:
|
|
|
|
case QJsonValue::Undefined:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
private:
|
|
|
|
|
|
|
|
static QJsonValue createValue(QJsonValue schema, bool ignoreRequired)
|
|
|
|
{
|
|
|
|
QJsonObject result;
|
|
|
|
QJsonObject obj = schema.toObject();
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (obj.find("type") != obj.end() && obj.find("type").value().isString())
|
|
|
|
{
|
|
|
|
QJsonValue ret = QJsonValue::Null;
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (obj.find("type").value().toString() == "object" && ( obj.find("required").value().toBool() || ignoreRequired ) )
|
|
|
|
ret = createValue(obj["properties"], ignoreRequired);
|
|
|
|
else if (obj.find("type").value().toString() == "array" && ( obj.find("required").value().toBool() || ignoreRequired ) )
|
|
|
|
{
|
|
|
|
QJsonArray array;
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (obj.find("default") != obj.end())
|
|
|
|
ret = obj.find("default").value();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = createValue(obj["items"], ignoreRequired);
|
|
|
|
|
|
|
|
if (!ret.toObject().isEmpty())
|
|
|
|
array.append(ret);
|
|
|
|
ret = array;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( obj.find("required").value().toBool() || ignoreRequired )
|
|
|
|
if (obj.find("default") != obj.end())
|
|
|
|
ret = obj.find("default").value();
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (QJsonObject::const_iterator i = obj.begin(); i != obj.end(); ++i)
|
|
|
|
{
|
|
|
|
QString attribute = i.key();
|
|
|
|
const QJsonValue & attributeValue = *i;
|
|
|
|
QJsonValue subValue = obj[attribute];
|
|
|
|
|
|
|
|
if (attributeValue.toObject().find("type") != attributeValue.toObject().end())
|
|
|
|
{
|
|
|
|
if (attributeValue.toObject().find("type").value().toString() == "object" && ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired ) )
|
|
|
|
{
|
|
|
|
if (obj.contains("properties"))
|
|
|
|
result[attribute] = createValue(obj["properties"], ignoreRequired);
|
|
|
|
else
|
|
|
|
result[attribute] = createValue(subValue, ignoreRequired);
|
|
|
|
}
|
|
|
|
else if (attributeValue.toObject().find("type").value().toString() == "array" && ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired ) )
|
|
|
|
{
|
|
|
|
QJsonArray array;
|
|
|
|
|
|
|
|
if (attributeValue.toObject().find("default") != attributeValue.toObject().end())
|
|
|
|
result[attribute] = attributeValue.toObject().find("default").value();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QJsonValue retEmpty;
|
|
|
|
retEmpty = createValue(attributeValue.toObject()["items"], ignoreRequired);
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (!retEmpty.toObject().isEmpty())
|
|
|
|
array.append(retEmpty);
|
|
|
|
result[attribute] = array;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired )
|
|
|
|
{
|
|
|
|
if (attributeValue.toObject().find("default") != attributeValue.toObject().end())
|
|
|
|
result[attribute] = attributeValue.toObject().find("default").value();
|
|
|
|
else
|
|
|
|
result[attribute] = QJsonValue::Null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void modifyValue(QJsonValue source, QJsonObject& target, QStringList path, const QJsonValue& newValue, QString& property)
|
|
|
|
{
|
|
|
|
QJsonObject obj = source.toObject();
|
|
|
|
|
|
|
|
if (!obj.isEmpty())
|
|
|
|
{
|
|
|
|
for (QJsonObject::iterator i = obj.begin(); i != obj.end(); ++i)
|
|
|
|
{
|
|
|
|
QString propertyName = i.key();
|
|
|
|
QJsonValue subValue = obj[propertyName];
|
|
|
|
|
|
|
|
if (subValue.isObject())
|
|
|
|
{
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
if (propertyName == path.first())
|
|
|
|
{
|
|
|
|
path.removeFirst();
|
|
|
|
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
QJsonObject obj;
|
|
|
|
modifyValue(subValue, obj, path, newValue, property);
|
|
|
|
subValue = obj;
|
|
|
|
}
|
|
|
|
else if (newValue != QJsonValue::Null)
|
|
|
|
subValue = newValue;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!subValue.toObject().isEmpty())
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (path.first() == property && newValue != QJsonValue::Null)
|
|
|
|
{
|
|
|
|
target[property] = newValue;
|
|
|
|
property = QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (!subValue.toObject().isEmpty())
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
else if (subValue.isArray())
|
|
|
|
{
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
if (propertyName == path.first())
|
|
|
|
{
|
|
|
|
path.removeFirst();
|
|
|
|
|
|
|
|
int arrayLevel = -1;
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
if ((path.first().left(1) == "[") && (path.first().right(1) == "]"))
|
|
|
|
{
|
|
|
|
arrayLevel = path.first().mid(1, path.first().size()-2).toInt();
|
|
|
|
path.removeFirst();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QJsonArray array = subValue.toArray();
|
|
|
|
QJsonArray json_array;
|
|
|
|
|
|
|
|
for (QJsonArray::iterator i = array.begin(); i != array.end(); ++i)
|
|
|
|
{
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
QJsonObject arr;
|
|
|
|
modifyValue(*i, arr, path, newValue, property);
|
|
|
|
subValue = arr;
|
|
|
|
}
|
|
|
|
else if (newValue != QJsonValue::Null)
|
|
|
|
subValue = newValue;
|
|
|
|
else
|
|
|
|
continue;
|
2020-08-08 23:12:43 +02:00
|
|
|
|
2017-07-30 13:32:10 +02:00
|
|
|
if (!subValue.toObject().isEmpty())
|
|
|
|
json_array.append(subValue);
|
|
|
|
else if (newValue != QJsonValue::Null && arrayLevel != -1)
|
|
|
|
json_array.append( (i - array.begin() == arrayLevel) ? subValue : *i );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!json_array.isEmpty())
|
|
|
|
target[propertyName] = json_array;
|
|
|
|
else if (newValue != QJsonValue::Null && arrayLevel == -1)
|
|
|
|
target[propertyName] = newValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (path.first() == property && newValue != QJsonValue::Null)
|
|
|
|
{
|
|
|
|
target[property] = newValue;
|
|
|
|
property = QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (!subValue.toArray().isEmpty())
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!path.isEmpty())
|
|
|
|
{
|
|
|
|
if (propertyName == path.first())
|
|
|
|
{
|
|
|
|
path.removeFirst();
|
|
|
|
|
|
|
|
if (path.isEmpty())
|
|
|
|
{
|
|
|
|
if (newValue != QJsonValue::Null && property.isEmpty())
|
|
|
|
subValue = newValue;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (path.first() == property && newValue != QJsonValue::Null)
|
|
|
|
{
|
|
|
|
target[property] = newValue;
|
|
|
|
property = QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
target[propertyName] = subValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (newValue != QJsonValue::Null && !property.isEmpty())
|
|
|
|
{
|
|
|
|
target[property] = newValue;
|
|
|
|
property = QString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|