5#include <QtCore/QApplicationStatic>
6#include <QtCore/QFileInfo>
7#include <QtCore/QJsonArray>
8#include <QtCore/QJsonParseError>
9#include <QtCore/QObject>
10#include <QtCore/QTranslator>
21 QJsonParseError parseError;
24 if (parseError.error == QJsonParseError::NoError) {
30 qCDebug(JsonParsingLog) <<
"Json read error (compressed input) offset" << parseError.offset;
32 const int startPos = qMax(0, parseError.offset - 100);
33 const int length = qMin(bytes.length() - startPos, 200);
34 qCDebug(JsonParsingLog) <<
"Json read error" << bytes.mid(startPos, length).constData();
36 errorString = QStringLiteral(
"%1 (offset %2)").arg(parseError.errorString()).arg(parseError.offset);
44 if (jsonBytes.isEmpty() && !
errorString.isEmpty()) {
54 if (value.type() == QJsonValue::Null) {
55 return std::numeric_limits<double>::quiet_NaN();
58 return value.toDouble();
69constexpr const char *_translateKeysKey =
"translateKeys";
70constexpr const char *_arrayIDKeysKey =
"_arrayIDKeys";
71constexpr const char *_jsonGroundStationKey =
"groundStation";
72constexpr const char *_jsonGroundStationValue =
"QGroundControl";
76QJsonObject translateObject(QJsonObject &jsonObject,
const QString &translateContext,
const QStringList &translateKeys);
78QJsonArray translateArray(QJsonArray &jsonArray,
const QString &translateContext,
const QStringList &translateKeys)
80 for (qsizetype i = 0; i < jsonArray.count(); i++) {
81 QJsonObject childJsonObject = jsonArray[i].toObject();
82 jsonArray[i] = translateObject(childJsonObject, translateContext, translateKeys);
87QJsonObject translateObject(QJsonObject &jsonObject,
const QString &translateContext,
const QStringList &translateKeys)
89 for (
const QString &key : jsonObject.
keys()) {
90 if (jsonObject[key].isString()) {
91 QString locString = jsonObject[key].toString();
92 if (!translateKeys.contains(key)) {
96 QString disambiguation;
97 const QString disambiguationPrefix(
"#loc.disambiguation#");
98 if (locString.startsWith(disambiguationPrefix)) {
99 locString = locString.right(locString.length() - disambiguationPrefix.length());
100 const int commentEndIndex = locString.indexOf(
"#");
101 if (commentEndIndex != -1) {
102 disambiguation = locString.left(commentEndIndex);
103 locString = locString.right(locString.length() - disambiguation.length() - 1);
108 translateContext.toUtf8().constData(),
109 locString.toUtf8().constData(),
110 disambiguation.toUtf8().constData());
111 if (!xlatString.isNull()) {
112 jsonObject[key] = xlatString;
114 }
else if (jsonObject[key].isArray()) {
115 QJsonArray childJsonArray = jsonObject[key].toArray();
116 jsonObject[key] = translateArray(childJsonArray, translateContext, translateKeys);
117 }
else if (jsonObject[key].isObject()) {
118 QJsonObject childJsonObject = jsonObject[key].toObject();
119 jsonObject[key] = translateObject(childJsonObject, translateContext, translateKeys);
128QStringList resolveTranslateKeys(QJsonObject &jsonObject,
129 const QStringList &defaultTranslateKeys,
130 const QStringList &defaultArrayIDKeys)
132 QString translateKeys;
133 if (jsonObject.contains(_translateKeysKey)) {
134 translateKeys = jsonObject[_translateKeysKey].toString();
135 }
else if (!defaultTranslateKeys.isEmpty()) {
136 translateKeys = defaultTranslateKeys.join(
",");
137 jsonObject[_translateKeysKey] = translateKeys;
140 if (!jsonObject.contains(_arrayIDKeysKey) && !defaultArrayIDKeys.isEmpty()) {
141 jsonObject[_arrayIDKeysKey] = defaultArrayIDKeys.join(
",");
144 if (translateKeys.isEmpty()) {
147 return translateKeys.split(
",");
156 return s_jsonTranslator();
161 jsonObject[_jsonGroundStationKey] = _jsonGroundStationValue;
167 int minSupportedVersion,
int maxSupportedVersion,
int &version,
170 static const QList<KeyValidateInfo> requiredKeys = {
180 if (fileTypeValue != expectedFileType) {
181 errorString = QObject::tr(
"Incorrect file type key expected:%1 actual:%2").arg(expectedFileType, fileTypeValue);
186 if (version < minSupportedVersion) {
187 errorString = QObject::tr(
"File version %1 is no longer supported").arg(version);
191 if (version > maxSupportedVersion) {
192 errorString = QObject::tr(
"File version %1 is newer than current supported version %2")
194 .arg(maxSupportedVersion);
202 int minSupportedVersion,
int maxSupportedVersion,
int &version,
205 static const QList<KeyValidateInfo> requiredKeys = {
206 {_jsonGroundStationKey, QJsonValue::String,
true},
218 int minSupportedVersion,
int maxSupportedVersion,
int &version,
220 const QStringList &defaultTranslateKeys,
221 const QStringList &defaultArrayIDKeys)
229 if (!doc.isObject()) {
230 errorString = QObject::tr(
"Root of json file is not object: %1").arg(jsonFilename);
234 QJsonObject jsonObject = doc.object();
242 const QStringList translateKeys = resolveTranslateKeys(jsonObject, defaultTranslateKeys, defaultArrayIDKeys);
243 const QString context = QFileInfo(jsonFilename).fileName();
244 return translateObject(jsonObject, context, translateKeys);
Q_APPLICATION_STATIC(ADSBVehicleManager, _adsbVehicleManager, SettingsManager::instance() ->adsbVehicleManagerSettings())
#define QGC_LOGGING_CATEGORY(name, categoryStr)
std::array< MsgOutKey, 4 > keys
bool validateExternalQGCJsonFile(const QJsonObject &jsonObject, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString)
bool validateInternalQGCJsonFile(const QJsonObject &jsonObject, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString)
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
bool isJsonFile(const QByteArray &bytes, QJsonDocument &jsonDoc, QString &errorString)
Determines whether an in-memory byte buffer contains parseable JSON content.
constexpr const char * jsonFileTypeKey
QJsonObject openInternalQGCJsonFile(const QString &jsonFilename, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString, const QStringList &defaultTranslateKeys, const QStringList &defaultArrayIDKeys)
double possibleNaNJsonValue(const QJsonValue &value)
Returns NaN if the value is null, or the value converted to double otherwise.
void saveQGCJsonFileHeader(QJsonObject &jsonObject, const QString &fileType, int version)
Saves the standard QGC file header (groundStation, fileType, version) into the json object.
QTranslator * translator()
Translator used by openInternalQGCJsonFile for localized strings.
constexpr const char * jsonVersionKey
bool looksLikeCompressedData(const QByteArray &data)
QByteArray readFile(const QString &filePath, QString *errorString, qint64 maxBytes)
Read file contents, transparently decompressing .gz/.xz/.zst/.bz2/.lz4 files.
QJsonDocument parseCompressedJson(const QByteArray &data, QJsonParseError *error)
Parse JSON from data that may be compressed. Auto-detects gzip/xz/zstd/bzip2/lz4.