refs #815 Throw CJsonException when required JSON objects are not found.

This commit is contained in:
Mathew Sutcliffe
2016-12-18 04:44:25 +00:00
parent 7c5c9d30e6
commit bbdbd26f82
10 changed files with 112 additions and 40 deletions

View File

@@ -122,13 +122,17 @@ namespace BlackMisc
void convertFromJson(const QJsonObject &json)
{
derived().clear();
QJsonArray array = json.value("containerbase").toArray();
QJsonValue value = json.value("containerbase");
if (value.isUndefined()) { throw CJsonException("Missing 'containerbase'"); }
QJsonArray array = value.toArray();
int index = 0;
for (auto i = array.begin(); i != array.end(); ++i)
{
CJsonScope scope("containerbase", index++);
QJsonValueRef ref = (*i);
T value;
ref >> value;
derived().insert(value);
T val;
ref >> val;
derived().insert(std::move(val));
}
}

View File

@@ -257,7 +257,10 @@ namespace BlackMisc
//! \copydoc BlackMisc::Mixin::JsonByMetaClass::convertFromJson
void convertFromJson(const QJsonObject &json)
{
QJsonArray array = json.value("associativecontainerbase").toArray();
QJsonValue value = json.value("associativecontainerbase");
if (value.isUndefined()) { throw CJsonException("Missing 'associativecontainerbase'"); }
QJsonArray array = value.toArray();
int index = 0;
for (auto it = array.begin(); it != array.end(); ++it)
{
QJsonValueRef jsonKey = (*it);
@@ -265,10 +268,16 @@ namespace BlackMisc
if (it == array.end()) { qWarning("Odd number of elements in CDictionary::convertFromJson"); return; }
QJsonValueRef jsonValue = (*it);
Key key;
Value value;
jsonKey >> key;
jsonValue >> value;
m_impl.insert(key, value);
Value val;
{
CJsonScope scope("associativecontainerbase", 2 * index);
jsonKey >> key;
}
{
CJsonScope scope("associativecontainerbase", 2 * index++ + 1);
jsonValue >> val;
}
m_impl.insert(std::move(key), std::move(val));
}
}

View File

@@ -16,6 +16,7 @@
#include "blackmisc/fileutils.h"
#include "blackmisc/inheritancetraits.h"
#include "blackmisc/metaclass.h"
#include "blackmisc/jsonexception.h"
#include <QByteArray>
#include <QJsonArray>
@@ -375,8 +376,17 @@ namespace BlackMisc
auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>());
meta.forEachMemberName(*derived(), [ & ](auto & member, CExplicitLatin1String name)
{
auto it = json.find(name);
if (it != json.end()) { it.value() >> member; }
const auto value = json.value(name);
if (value.isUndefined())
{
constexpr bool required = false; // \todo add RequiredForJson flag in metaclass system
if (required) { throw CJsonException(QStringLiteral("Missing required member '%1'").arg(name.m_latin1)); }
}
else
{
CJsonScope scope(name.m_latin1);
value >> member;
}
});
}

View File

@@ -194,8 +194,9 @@ namespace BlackMisc
void CUrl::convertFromJson(const QJsonObject &json)
{
QString url(json.value("url").toString());
this->setFullUrl(url);
const QJsonValue value = json.value("url");
if (value.isUndefined()) { throw CJsonException("Missing 'url'"); }
this->setFullUrl(value.toString());
}
int CUrl::protocolToDefaultPort(const QString &protocol)

View File

@@ -348,9 +348,13 @@ namespace BlackMisc
template <class MU, class PQ>
void CPhysicalQuantity<MU, PQ>::convertFromJson(const QJsonObject &json)
{
const QString unitSymbol = json.value("unit").toString();
this->setUnitBySymbol(unitSymbol);
this->m_value = json.value("value").toDouble();
const QJsonValue unit = json.value("unit");
const QJsonValue value = json.value("value");
if (unit.isUndefined()) { throw CJsonException("Missing 'unit'"); }
if (value.isUndefined()) { throw CJsonException("Missing 'value'"); }
this->setUnitBySymbol(unit.toString());
this->m_value = value.toDouble();
}
template <class MU, class PQ>

View File

@@ -698,13 +698,34 @@ namespace BlackMisc
void CAircraftModelList::convertFromMemoizedJson(const QJsonObject &json)
{
clear();
QJsonArray array = json.value("containerbase").toArray();
QJsonValue value = json.value("containerbase");
if (value.isUndefined()) { throw CJsonException("Missing 'containerbase'"); }
QJsonArray array = value.toArray();
CAircraftModel::MemoHelper::CUnmemoizer helper;
helper.getTable<CAircraftIcaoCode>().convertFromJson(json.value("aircraftIcaos").toObject());
helper.getTable<CLivery>().convertFromJson(json.value("liveries").toObject());
helper.getTable<CDistributor>().convertFromJson(json.value("distributors").toObject());
QJsonValue aircraftIcaos = json.value("aircraftIcaos");
QJsonValue liveries = json.value("liveries");
QJsonValue distributors = json.value("distributors");
if (aircraftIcaos.isUndefined()) { throw CJsonException("Missing 'aircraftIcaos'"); }
if (liveries.isUndefined()) { throw CJsonException("Missing 'liveries'"); }
if (distributors.isUndefined()) { throw CJsonException("Missing 'distributors'"); }
{
CJsonScope scope("aircraftIcaos");
helper.getTable<CAircraftIcaoCode>().convertFromJson(aircraftIcaos.toObject());
}
{
CJsonScope scope("liveries");
helper.getTable<CLivery>().convertFromJson(liveries.toObject());
}
{
CJsonScope scope("distributors");
helper.getTable<CDistributor>().convertFromJson(distributors.toObject());
}
int index = 0;
for (auto i = array.begin(); i != array.end(); ++i)
{
CJsonScope scope("containerbase", index++);
CAircraftModel value;
value.convertFromMemoizedJson(i->toObject(), helper);
insert(value);

View File

@@ -27,7 +27,10 @@ namespace BlackMisc
{
if (json.contains("IID")) // comes from the plugin
{
if (! json.contains("MetaData")) { throw CJsonException("Missing 'MetaData'"); }
// json data is already validated by CPluginManagerSimulator
CJsonScope scope("MetaData");
CValueObject::convertFromJson(json["MetaData"].toObject());
m_valid = true;
}

View File

@@ -156,38 +156,43 @@ namespace BlackMisc
{
// Remark: Names "type" and "value" are also used for drag and drop
// Changing the names here requires the change for drag and drop too
QString typeName = json.value("type").toString();
QJsonValue typeValue = json.value("type");
if (typeValue.isUndefined()) { throw CJsonException("Missing 'type'"); }
QString typeName = typeValue.toString();
if (typeName.isEmpty()) { m_v.clear(); return; }
int typeId = QMetaType::type(qPrintable(typeName));
QJsonValue value = json.value("value");
if (value.isUndefined() && typeId != QVariant::Invalid) { throw CJsonException("Missing 'value'"); }
switch (typeId)
{
case QVariant::Invalid: CLogMessage(this).warning("Invalid type for fromJson: %1") << typeName; m_v.clear(); break;
case QVariant::Int: m_v.setValue(json.value("value").toInt()); break;
case QVariant::UInt: m_v.setValue<uint>(json.value("value").toInt()); break;
case QVariant::Bool: m_v.setValue(json.value("value").toBool()); break;
case QVariant::Double: m_v.setValue(json.value("value").toDouble()); break;
case QVariant::LongLong: m_v.setValue<qlonglong>(json.value("value").toInt()); break; // QJsonValue has no toLongLong() method???
case QVariant::ULongLong: m_v.setValue<qulonglong>(json.value("value").toInt()); break;
case QVariant::String: m_v.setValue(json.value("value").toString()); break;
case QVariant::Char: m_v.setValue(json.value("value").toString().size() > 0 ? json.value("value").toString().at(0) : '\0'); break;
case QVariant::ByteArray: m_v.setValue(json.value("value").toString().toLatin1()); break;
case QVariant::DateTime: m_v.setValue(QDateTime::fromString(json.value("value").toString(), Qt::ISODate)); break;
case QVariant::Date: m_v.setValue(QDate::fromString(json.value("value").toString(), Qt::ISODate)); break;
case QVariant::Time: m_v.setValue(QTime::fromString(json.value("value").toString(), Qt::ISODate)); break;
case QVariant::StringList: m_v.setValue(QVariant(json.value("value").toArray().toVariantList()).toStringList()); break;
case QVariant::Int: m_v.setValue(value.toInt()); break;
case QVariant::UInt: m_v.setValue<uint>(value.toInt()); break;
case QVariant::Bool: m_v.setValue(value.toBool()); break;
case QVariant::Double: m_v.setValue(value.toDouble()); break;
case QVariant::LongLong: m_v.setValue<qlonglong>(value.toInt()); break; // QJsonValue has no toLongLong() method???
case QVariant::ULongLong: m_v.setValue<qulonglong>(value.toInt()); break;
case QVariant::String: m_v.setValue(value.toString()); break;
case QVariant::Char: m_v.setValue(value.toString().size() > 0 ? value.toString().at(0) : '\0'); break;
case QVariant::ByteArray: m_v.setValue(value.toString().toLatin1()); break;
case QVariant::DateTime: m_v.setValue(QDateTime::fromString(value.toString(), Qt::ISODate)); break;
case QVariant::Date: m_v.setValue(QDate::fromString(value.toString(), Qt::ISODate)); break;
case QVariant::Time: m_v.setValue(QTime::fromString(value.toString(), Qt::ISODate)); break;
case QVariant::StringList: m_v.setValue(QVariant(value.toArray().toVariantList()).toStringList()); break;
default:
try
{
auto *meta = Private::getValueObjectMetaInfo(typeId);
if (meta)
{
CJsonScope scope("value");
m_v = QVariant(typeId, nullptr);
meta->convertFromJson(json.value("value").toObject(), data());
meta->convertFromJson(value.toObject(), data());
}
else if (QMetaType::hasRegisteredConverterFunction(qMetaTypeId<QString>(), typeId))
{
m_v.setValue(json.value("value").toString());
m_v.setValue(value.toString());
if (! m_v.convert(typeId))
{
CLogMessage(this).warning("Failed to convert from JSON string");
@@ -231,15 +236,21 @@ namespace BlackMisc
void CVariant::convertFromMemoizedJson(const QJsonObject &json)
{
QString typeName = json.value("type").toString();
QJsonValue typeValue = json.value("type");
if (typeValue.isUndefined()) { throw CJsonException("Missing 'type'"); }
QString typeName = typeValue.toString();
if (typeName.isEmpty()) { m_v.clear(); return; }
int typeId = QMetaType::type(qPrintable(typeName));
auto *meta = Private::getValueObjectMetaInfo(typeId);
if (meta)
{
QJsonValue value = json.value("value");
if (value.isUndefined()) { throw CJsonException("Missing 'value'"); }
CJsonScope scope("value");
m_v = QVariant(typeId, nullptr);
meta->convertFromMemoizedJson(json.value("value").toObject(), data());
meta->convertFromMemoizedJson(value.toObject(), data());
}
else
{

View File

@@ -35,9 +35,11 @@ namespace BlackMisc
clear();
for (auto it = json.begin(); it != json.end(); ++it)
{
const QString key = it.key();
CJsonScope scope(key);
CVariant value;
value.convertFromJson(it.value().toObject());
implementationOf(*this).insert(cend(), it.key(), value);
implementationOf(*this).insert(cend(), key, value);
}
}
@@ -48,6 +50,7 @@ namespace BlackMisc
{
auto value = json.value(key);
if (value.isUndefined()) { continue; }
CJsonScope scope(key);
CVariant var;
var.convertFromJson(value.toObject());
insert(key, var);
@@ -75,9 +78,11 @@ namespace BlackMisc
clear();
for (auto it = json.begin(); it != json.end(); ++it)
{
const QString key = it.key();
CJsonScope scope(key);
CVariant value;
value.convertFromMemoizedJson(it.value().toObject());
implementationOf(*this).insert(cend(), it.key(), value);
implementationOf(*this).insert(cend(), key, value);
}
}
@@ -88,6 +93,7 @@ namespace BlackMisc
{
auto value = json.value(key);
if (value.isUndefined()) { continue; }
CJsonScope scope(key);
CVariant var;
var.convertFromMemoizedJson(value.toObject());
insert(key, var);

View File

@@ -26,7 +26,10 @@ namespace BlackMisc
{
if (json.contains("IID")) // comes from the plugin
{
if (! json.contains("MetaData")) { throw CJsonException("Missing 'MetaData'"); }
// json data is already validated by CPluginManagerWeatherData
CJsonScope scope("MetaData");
CValueObject::convertFromJson(json["MetaData"].toObject());
m_valid = true;
}