JsonHelper.h 12.2 KB
Newer Older
1 2
/****************************************************************************
 *
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10
#pragma once
Don Gagne's avatar
Don Gagne committed
11 12

#include <QJsonObject>
13
#include <QVariantList>
Don Gagne's avatar
Don Gagne committed
14
#include <QGeoCoordinate>
15 16 17 18
#include <QCoreApplication>

/// @file
/// @author Don Gagne <don@thegagnes.com>
Don Gagne's avatar
Don Gagne committed
19

20 21
class QmlObjectListModel;

22 23
/// @brief Json manipulation helper class.
/// Primarily used for parsing and processing Fact metadata.
Don Gagne's avatar
Don Gagne committed
24 25
class JsonHelper
{
26 27
    Q_DECLARE_TR_FUNCTIONS(JsonHelper)

Don Gagne's avatar
Don Gagne committed
28
public:
29 30 31 32 33 34
    /// Determines is the specified file is a json file
    /// @return true: file is json, false: file is not json
    static bool isJsonFile(const QString&       fileName,       ///< filename
                           QJsonDocument&       jsonDoc,        ///< returned json document
                           QString&             errorString);   ///< error on parse failure

35 36
    /// Determines is the specified data is a json file
    /// @return true: file is json, false: file is not json
37 38 39 40 41 42 43 44
    static bool isJsonFile(const QByteArray&    bytes,          ///< json bytes
                           QJsonDocument&       jsonDoc,        ///< returned json document
                           QString&             errorString);   ///< error on parse failure

    /// Saves the standard file header the json object
    static void saveQGCJsonFileHeader(QJsonObject&      jsonObject, ///< root json object
                                      const QString&    fileType,   ///< file type for file
                                      int               version);   ///< version number for file
45

46
    /// Validates the standard parts of an external QGC json file (Plan file, ...):
47 48
    ///     jsonFileTypeKey - Required and checked to be equal to expectedFileType
    ///     jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion
Don Gagne's avatar
Don Gagne committed
49
    ///     jsonGroundStationKey - Required and checked to be string type
50
    /// @return false: validation failed, errorString set
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    static bool validateExternalQGCJsonFile(const QJsonObject&  jsonObject,             ///< json object to validate
                                            const QString&      expectedFileType,       ///< correct file type for file
                                            int                 minSupportedVersion,    ///< minimum supported version
                                            int                 maxSupportedVersion,    ///< maximum supported major version
                                            int                 &version,               ///< returned file version
                                            QString&            errorString);           ///< returned error string if validation fails

    /// Validates the standard parts of a internal QGC json file (FactMetaData, ...):
    ///     jsonFileTypeKey - Required and checked to be equal to expectedFileType
    ///     jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion
    ///     jsonGroundStationKey - Required and checked to be string type
    /// @return false: validation failed, errorString set
    static bool validateInternalQGCJsonFile(const QJsonObject&  jsonObject,             ///< json object to validate
                                            const QString&      expectedFileType,       ///< correct file type for file
                                            int                 minSupportedVersion,    ///< minimum supported version
                                            int                 maxSupportedVersion,    ///< maximum supported major version
                                            int                 &version,               ///< returned file version
                                            QString&            errorString);           ///< returned error string if validation fails

    // Opens, validates and translates an internal QGC json file.
    // @return Json root object for file. Empty QJsonObject if error.
    static QJsonObject openInternalQGCJsonFile(const QString& jsonFilename,             ///< Json file to open
                                               const QString&      expectedFileType,    ///< correct file type for file
                                               int                 minSupportedVersion, ///< minimum supported version
                                               int                 maxSupportedVersion, ///< maximum supported major version
                                               int                 &version,            ///< returned file version
                                               QString&            errorString);        ///< returned error string if validation fails
78

79 80 81 82 83 84 85 86 87 88 89 90
    /// Validates that the specified keys are in the object
    /// @return false: validation failed, errorString set
    static bool validateRequiredKeys(const QJsonObject& jsonObject, ///< json object to validate
                                     const QStringList& keys,       ///< keys which are required to be present
                                     QString& errorString);         ///< returned error string if validation fails

    /// Validates the types of specified keys are in the object
    /// @return false: validation failed, errorString set
    static bool validateKeyTypes(const QJsonObject& jsonObject,         ///< json object to validate
                                 const QStringList& keys,               ///< keys to validate
                                 const QList<QJsonValue::Type>& types,  ///< required type for each key, QJsonValue::Null specifies double with possible NaN
                                 QString& errorString);                 ///< returned error string if validation fails
91

Don Gagne's avatar
Don Gagne committed
92 93
    typedef struct {
        const char*         key;        ///< json key name
94
        QJsonValue::Type    type;       ///< required type for key, QJsonValue::Null specifies double with possible NaN
Don Gagne's avatar
Don Gagne committed
95 96 97 98 99
        bool                required;   ///< true: key must be present
    } KeyValidateInfo;

    static bool validateKeys(const QJsonObject& jsonObject, const QList<KeyValidateInfo>& keyInfo, QString& errorString);

100
    /// Loads a QGeoCoordinate
101
    ///     Stored as array [ lat, lon, alt ]
102
    /// @return false: validation failed
103 104 105 106 107
    static bool loadGeoCoordinate(const QJsonValue& jsonValue,              ///< json value to load from
                                  bool              altitudeRequired,       ///< true: altitude must be specified
                                  QGeoCoordinate&   coordinate,             ///< returned QGeoCordinate
                                  QString&          errorString,            ///< returned error string if load failure
                                  bool              geoJsonFormat = false); ///< if true, use [lon, lat], [lat, lon] otherwise
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    /// Saves a QGeoCoordinate
    ///     Stored as array [ lat, lon, alt ]
    static void saveGeoCoordinate(const QGeoCoordinate& coordinate,     ///< QGeoCoordinate to save
                                  bool                  writeAltitude,  ///< true: write altitude to json
                                  QJsonValue&           jsonValue);     ///< json value to save to

    /// Loads a QGeoCoordinate
    ///     Stored as array [ lon, lat, alt ]
    /// @return false: validation failed
    static bool loadGeoJsonCoordinate(const QJsonValue& jsonValue,          ///< json value to load from
                                      bool              altitudeRequired,   ///< true: altitude must be specified
                                      QGeoCoordinate&   coordinate,         ///< returned QGeoCordinate
                                      QString&          errorString);       ///< returned error string if load failure

    /// Saves a QGeoCoordinate
    ///     Stored as array [ lon, lat, alt ]
    static void saveGeoJsonCoordinate(const QGeoCoordinate& coordinate,     ///< QGeoCoordinate to save
                                      bool                  writeAltitude,  ///< true: write altitude to json
                                      QJsonValue&           jsonValue);     ///< json value to save to

129 130 131 132 133 134
    /// Loads a polygon from an array
    static bool loadPolygon(const QJsonArray&   polygonArray,   ///< Array of coordinates
                            QmlObjectListModel& list,           ///< Empty list to add vertices to
                            QObject*            parent,         ///< parent for newly allocated QGCQGeoCoordinates
                            QString&            errorString);   ///< returned error string if load failure

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
    /// Loads a list of QGeoCoordinates from a json array
    /// @return false: validation failed
    static bool loadGeoCoordinateArray(const QJsonValue&    jsonValue,              ///< json value which contains points
                                       bool                 altitudeRequired,       ///< true: altitude field must be specified
                                       QVariantList&        rgVarPoints,            ///< returned points
                                       QString&             errorString);           ///< returned error string if load failure
    static bool loadGeoCoordinateArray(const QJsonValue&        jsonValue,          ///< json value which contains points
                                       bool                     altitudeRequired,   ///< true: altitude field must be specified
                                       QList<QGeoCoordinate>&   rgPoints,           ///< returned points
                                       QString&                 errorString);       ///< returned error string if load failure

    /// Saves a list of QGeoCoordinates to a json array
    static void saveGeoCoordinateArray(const QVariantList&  rgVarPoints,            ///< points to save
                                       bool                 writeAltitude,          ///< true: write altitide value
                                       QJsonValue&          jsonValue);             ///< json value to save to
    static void saveGeoCoordinateArray(const QList<QGeoCoordinate>& rgPoints,       ///< points to save
                                       bool                         writeAltitude,  ///< true: write altitide value
                                       QJsonValue&                  jsonValue);     ///< json value to save to

154 155 156 157
    /// Saves a polygon to a json array
    static void savePolygon(QmlObjectListModel& list,           ///< List which contains vertices
                            QJsonArray&         polygonArray);  ///< Array to save into

158
    /// Returns NaN if the value is null, or if not, the double value
159
    static double possibleNaNJsonValue(const QJsonValue& value);
160

161 162 163 164 165 166
    static const char* jsonVersionKey;
    static const char* jsonGroundStationKey;
    static const char* jsonGroundStationValue;
    static const char* jsonFileTypeKey;

private:
Don Gagne's avatar
Don Gagne committed
167
    static QString _jsonValueTypeToString(QJsonValue::Type type);
168 169 170 171 172 173 174 175 176
    static bool _loadGeoCoordinate(const QJsonValue&    jsonValue,
                                   bool                 altitudeRequired,
                                   QGeoCoordinate&      coordinate,
                                   QString&             errorString,
                                   bool                 geoJsonFormat);
    static void _saveGeoCoordinate(const QGeoCoordinate&    coordinate,
                                   bool                     writeAltitude,
                                   QJsonValue&              jsonValue,
                                   bool                     geoJsonFormat);
177 178 179 180
    static QStringList _addDefaultLocKeys(QJsonObject& jsonObject);
    static QJsonObject _translateRoot(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys);
    static QJsonObject _translateObject(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys);
    static QJsonArray _translateArray(QJsonArray& jsonArray, const QString& translateContext, const QStringList& translateKeys);
Don Gagne's avatar
Don Gagne committed
181

182 183
    static const char*  _translateKeysKey;
    static const char*  _arrayIDKeysKey;
Don Gagne's avatar
Don Gagne committed
184
};