refs #815 Catch and handle CJsonException when calling convertFromJson.

This commit is contained in:
Mathew Sutcliffe
2016-12-21 02:27:21 +00:00
parent 4f6d3ed3a3
commit 51c3ae8c25
8 changed files with 65 additions and 18 deletions

View File

@@ -1148,6 +1148,8 @@ namespace BlackCore
if (!simAircraft.isPartsSynchronized() && !isFull) { return; } if (!simAircraft.isPartsSynchronized() && !isFull) { return; }
CAircraftParts parts; CAircraftParts parts;
try
{
if (isFull) if (isFull)
{ {
parts.convertFromJson(jsonObject); parts.convertFromJson(jsonObject);
@@ -1159,6 +1161,13 @@ namespace BlackCore
QJsonObject config = applyIncrementalObject(parts.toJson(), jsonObject); QJsonObject config = applyIncrementalObject(parts.toJson(), jsonObject);
parts.convertFromJson(config); parts.convertFromJson(config);
} }
}
catch (const CJsonException &ex)
{
CStatusMessage message = ex.toStatusMessage(this, "Invalid parts packet");
message.setSeverity(CStatusMessage::SeverityDebug);
CLogMessage::preformatted(message);
}
// make sure in any case right time // make sure in any case right time
parts.setCurrentUtcTime(); parts.setCurrentUtcTime();

View File

@@ -175,7 +175,7 @@ namespace BlackCore
CApplicationInfoList CApplication::getRunningApplications() CApplicationInfoList CApplication::getRunningApplications()
{ {
CApplicationInfoList apps; CApplicationInfoList apps;
apps.convertFromJson(CFileUtils::readLockedFileToString(swiftDataRoot() + "apps.json")); apps.convertFromJsonNoThrow(CFileUtils::readLockedFileToString(swiftDataRoot() + "apps.json"), {}, {});
apps.removeIf([](const CApplicationInfo &info) { return !info.processInfo().exists(); }); apps.removeIf([](const CApplicationInfo &info) { return !info.processInfo().exists(); });
return apps; return apps;
} }

View File

@@ -413,7 +413,15 @@ namespace BlackGui
} }
CFlightPlan fp; CFlightPlan fp;
try
{
fp.convertFromJson(json); fp.convertFromJson(json);
}
catch (const CJsonException &ex)
{
m = ex.toStatusMessage(this, "Parse error in " + fileName);
break;
}
this->fillWithFlightPlanData(fp); this->fillWithFlightPlanData(fp);
} }
while (false); while (false);

View File

@@ -124,7 +124,16 @@ namespace BlackGui
CLogMessage(this).validationError("Parse error: %1") << jsonError.errorString(); CLogMessage(this).validationError("Parse error: %1") << jsonError.errorString();
return; return;
} }
try
{
parts.convertFromJson(jsonDoc.object()); parts.convertFromJson(jsonDoc.object());
}
catch (const CJsonException &ex)
{
ex.toLogMessage(this, "Parse error");
return;
}
partsToGui(parts); partsToGui(parts);
} }
else else

View File

@@ -149,7 +149,8 @@ namespace BlackGui
if (typeName.isEmpty() || typeId == QMetaType::UnknownType) { return CVariant(); } if (typeName.isEmpty() || typeId == QMetaType::UnknownType) { return CVariant(); }
CVariant valueVariant; CVariant valueVariant;
valueVariant.convertFromJson(jsonObj); const CStatusMessage status = valueVariant.convertFromJsonNoThrow(jsonObj, {}, {});
if (status.isFailure()) { return CVariant(); }
return valueVariant; return valueVariant;
} }

View File

@@ -763,7 +763,7 @@ namespace BlackMisc
auto json = QJsonDocument::fromJson(file.readAll()).object(); auto json = QJsonDocument::fromJson(file.readAll()).object();
QUuid uuid(json.value("uuid").toString()); QUuid uuid(json.value("uuid").toString());
CSequence<CProcessInfo> apps; CSequence<CProcessInfo> apps;
apps.convertFromJson(json.value("apps").toObject()); auto status = apps.convertFromJsonNoThrow(json.value("apps").toObject(), this, QStringLiteral("Error in %1 apps object").arg(m_filename));
apps.removeIf([](const CProcessInfo &pi) { return ! pi.exists(); }); apps.removeIf([](const CProcessInfo &pi) { return ! pi.exists(); });
if (apps.isEmpty()) { uuid = CIdentifier().toUuid(); } if (apps.isEmpty()) { uuid = CIdentifier().toUuid(); }

View File

@@ -329,7 +329,15 @@ namespace BlackMisc
{ {
CVariantMap map; CVariantMap map;
map.convertFromMemoizedJson(json); map.convertFromMemoizedJson(json);
insertValues({ map, QDateTime::currentMSecsSinceEpoch() }); if (! map.isEmpty()) { insertValues({ map, QDateTime::currentMSecsSinceEpoch() }); }
}
CStatusMessageList CValueCache::loadFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
{
CVariantMap map;
auto messages = map.convertFromMemoizedJsonNoThrow(json, categories, prefix);
if (! map.isEmpty()) { insertValues({ map, QDateTime::currentMSecsSinceEpoch() }); }
return messages;
} }
CStatusMessage CValueCache::saveToFiles(const QString &dir, const QString &keyPrefix) CStatusMessage CValueCache::saveToFiles(const QString &dir, const QString &keyPrefix)
@@ -418,6 +426,7 @@ namespace BlackMisc
keysInFiles.insert(filename.completeBaseName(), {}); keysInFiles.insert(filename.completeBaseName(), {});
} }
} }
bool ok = true;
for (auto it = keysInFiles.cbegin(); it != keysInFiles.cend(); ++it) for (auto it = keysInFiles.cbegin(); it != keysInFiles.cend(); ++it)
{ {
QFile file(dir + "/" + it.key() + ".json"); QFile file(dir + "/" + it.key() + ".json");
@@ -435,13 +444,19 @@ namespace BlackMisc
return CStatusMessage(this).error("Invalid JSON format in %1") << file.fileName(); return CStatusMessage(this).error("Invalid JSON format in %1") << file.fileName();
} }
CVariantMap temp; CVariantMap temp;
temp.convertFromMemoizedJson(json.object(), it.value()); const QString messagePrefix = QStringLiteral("Parsing %1.json").arg(it.key());
if (it.value().isEmpty()) { temp.convertFromMemoizedJson(json.object()); } auto messages = temp.convertFromMemoizedJsonNoThrow(json.object(), it.value(), this, messagePrefix);
if (it.value().isEmpty()) { messages.push_back(temp.convertFromMemoizedJsonNoThrow(json.object(), this, messagePrefix)); }
if (! messages.isEmpty())
{
ok = false;
CLogMessage::preformatted(messages);
}
temp.removeDuplicates(currentValues); temp.removeDuplicates(currentValues);
o_values.insert(temp, QFileInfo(file).lastModified().toMSecsSinceEpoch()); o_values.insert(temp, QFileInfo(file).lastModified().toMSecsSinceEpoch());
} }
return CStatusMessage(this).info("Loaded cache values %1 from %2") << return CStatusMessage(this).info("Loaded cache values %1 from %2 %3") <<
(keysMessage.isEmpty() ? o_values.keys().to<QStringList>().join(",") : keysMessage) << dir; (keysMessage.isEmpty() ? o_values.keys().to<QStringList>().join(",") : keysMessage) << dir << (ok ? "successfully" : "with errors");
} }
void CValueCache::markAllAsSaved(const QString &keyPrefix) void CValueCache::markAllAsSaved(const QString &keyPrefix)

View File

@@ -21,7 +21,7 @@
#include "blackmisc/propertyindex.h" #include "blackmisc/propertyindex.h"
#include "blackmisc/range.h" #include "blackmisc/range.h"
#include "blackmisc/slot.h" #include "blackmisc/slot.h"
#include "blackmisc/statusmessage.h" #include "blackmisc/statusmessagelist.h"
#include "blackmisc/valuecacheprivate.h" #include "blackmisc/valuecacheprivate.h"
#include "blackmisc/variant.h" #include "blackmisc/variant.h"
#include "blackmisc/variantmap.h" #include "blackmisc/variantmap.h"
@@ -193,9 +193,14 @@ namespace BlackMisc
//! Load all values in Json format. //! Load all values in Json format.
//! Values already in the cache will remain in the cache unless they are overwritten. //! Values already in the cache will remain in the cache unless they are overwritten.
//! \throws BlackMisc::CJsonException if JSON schema validation fails.
//! \threadsafe //! \threadsafe
void loadFromJson(const QJsonObject &json); void loadFromJson(const QJsonObject &json);
//! Call loadFromJson, catch any CJsonException that are thrown and return them as CStatusMessage.
//! \threadsafe
CStatusMessageList loadFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix);
//! Save values to Json files in a given directory. //! Save values to Json files in a given directory.
//! If prefix is provided then only those values whose keys start with that prefix. //! If prefix is provided then only those values whose keys start with that prefix.
//! \threadsafe //! \threadsafe