QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
JsonParsing.cc
Go to the documentation of this file.
1#include "JsonParsing.h"
2
3#include <limits>
4
5#include <QtCore/QObject>
6#include <QtCore/QJsonParseError>
7
8#include "QGCFileHelper.h"
10#include "QGCNetworkHelper.h"
11
12QGC_LOGGING_CATEGORY(JsonParsingLog, "Utilities.Parsing.Json")
13
14namespace {
15
16QString jsonValueTypeToString(QJsonValue::Type type)
17{
18 struct TypeToString
19 {
20 QJsonValue::Type type;
21 const char* string;
22 };
23
24 static constexpr const TypeToString typeToStringMap[] = {
25 {QJsonValue::Null, "NULL"}, {QJsonValue::Bool, "Bool"}, {QJsonValue::Double, "Double"},
26 {QJsonValue::String, "String"}, {QJsonValue::Array, "Array"}, {QJsonValue::Object, "Object"},
27 {QJsonValue::Undefined, "Undefined"},
28 };
29
30 for (const TypeToString& entry : typeToStringMap) {
31 if (type == entry.type) {
32 return entry.string;
33 }
34 }
35
36 return QObject::tr("Unknown type: %1").arg(type);
37}
38
39} // namespace
40
41namespace JsonParsing {
42
43bool validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString)
44{
45 QString missingKeys;
46
47 for (const QString& key : keys) {
48 if (!jsonObject.contains(key)) {
49 if (!missingKeys.isEmpty()) {
50 missingKeys += QStringLiteral(", ");
51 }
52 missingKeys += key;
53 }
54 }
55
56 if (!missingKeys.isEmpty()) {
57 errorString = QObject::tr("The following required keys are missing: %1").arg(missingKeys);
58 return false;
59 }
60
61 return true;
62}
63
64bool validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types,
65 QString& errorString)
66{
67 if (keys.count() != types.count()) {
68 errorString = QObject::tr("Mismatched key and type list sizes: keys=%1 types=%2")
69 .arg(keys.count()).arg(types.count());
70 return false;
71 }
72
73 for (qsizetype i = 0; i < types.count(); i++) {
74 const QString& valueKey = keys[i];
75 if (jsonObject.contains(valueKey)) {
76 const QJsonValue& jsonValue = jsonObject[valueKey];
77 if ((jsonValue.type() == QJsonValue::Double) && (types[i] == QJsonValue::Null)) {
78 // Null type signals a possible NaN on a double value.
79 continue;
80 }
81 if (jsonValue.type() != types[i]) {
82 errorString = QObject::tr("Incorrect value type - key:type:expected %1:%2:%3")
83 .arg(valueKey, jsonValueTypeToString(jsonValue.type()),
84 jsonValueTypeToString(types[i]));
85 return false;
86 }
87 }
88 }
89
90 return true;
91}
92
93bool isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc, QString& errorString)
94{
95 QJsonParseError parseError;
96 jsonDoc = QGCNetworkHelper::parseCompressedJson(bytes, &parseError);
97
98 if (parseError.error == QJsonParseError::NoError) {
99 return true;
100 }
101
102 const int startPos = qMax(0, parseError.offset - 100);
103 const int length = qMin(bytes.length() - startPos, 200);
104 qCDebug(JsonParsingLog) << "Json read error" << bytes.mid(startPos, length).constData();
105 errorString = parseError.errorString();
106
107 return false;
108}
109
110bool isJsonFile(const QString& fileName, QJsonDocument& jsonDoc, QString& errorString)
111{
112 const QByteArray jsonBytes = QGCFileHelper::readFile(fileName, &errorString);
113 if (jsonBytes.isEmpty() && !errorString.isEmpty()) {
114 return false;
115 }
116
117 return isJsonFile(jsonBytes, jsonDoc, errorString);
118}
119
120double possibleNaNJsonValue(const QJsonValue& value)
121{
122 if (value.type() == QJsonValue::Null) {
123 return std::numeric_limits<double>::quiet_NaN();
124 }
125
126 return value.toDouble();
127}
128
129} // namespace JsonParsing
QString errorString
#define QGC_LOGGING_CATEGORY(name, categoryStr)
bool validateKeyTypes(const QJsonObject &jsonObject, const QStringList &keys, const QList< QJsonValue::Type > &types, QString &errorString)
bool isJsonFile(const QByteArray &bytes, QJsonDocument &jsonDoc, QString &errorString)
Determines whether an in-memory byte buffer contains parseable JSON content.
double possibleNaNJsonValue(const QJsonValue &value)
Returns NaN if the value is null, or the value converted to double otherwise.
bool validateRequiredKeys(const QJsonObject &jsonObject, const QStringList &keys, QString &errorString)
Validates that all listed keys are present in the object.
QByteArray readFile(const QString &filePath, QString *errorString, qint64 maxBytes)
QJsonDocument parseCompressedJson(const QByteArray &data, QJsonParseError *error)