枢覆引 发表于 2025-6-7 09:52:43

Qt中使用QJsonDocument实现安全的JSON序列化/反序列化方案,包含详细的错误处理机制

以下是在Qt中使用QJsonDocument实现安全的JSON序列化/反序列化方案,包含详细的错误处理机制:
1. 基础错误处理架构

class JsonSerializable {
public:
    virtual ~JsonSerializable() = default;

    // 序列化接口
    [] bool serialize(QByteArray &output) const {
      QJsonObject jsonObj;
      if (!toJson(jsonObj)) {
            m_lastError = "Serialization failed: " + m_lastError;
            return false;
      }
      
      // 生成紧凑格式JSON(改用QJsonDocument::Indented可调格式)
      output = QJsonDocument(jsonObj).toJson(QJsonDocument::Compact);
      return true;
    }

    // 反序列化接口
    [] bool deserialize(const QByteArray &input) {
      QJsonParseError parseError;
      QJsonDocument doc = QJsonDocument::fromJson(input, &parseError);
      
      if (parseError.error != QJsonParseError::NoError) {
            m_lastError = QString("JSON parse error at %1: %2")
                        .arg(parseError.offset)
                        .arg(parseError.errorString());
            return false;
      }
      
      if (!doc.isObject()) {
            m_lastError = "Root is not a JSON object";
            return false;
      }
      
      return fromJson(doc.object());
    }

    // 错误信息访问
    QString lastError() const { return m_lastError; }

protected:
    // 子类必须实现的JSON转换方法
    virtual bool toJson(QJsonObject &json) const = 0;
    virtual bool fromJson(const QJsonObject &json) = 0;

    // 错误处理辅助方法
    void setError(const QString &error) { m_lastError = error; }
    bool validateField(const QJsonObject &json,
                      const QString &key,
                      QJsonValue::Type expectedType) {
      if (!json.contains(key)) {
            m_lastError = QString("Missing required field: %1").arg(key);
            return false;
      }
      if (json.type() != expectedType) {
            m_lastError = QString("Field '%1' type mismatch (Expect:%2 Got:%3)")
                        .arg(key)
                        .arg(typeToString(expectedType))
                        .arg(typeToString(json.type()));
            return false;
      }
      return true;
    }

private:
    QString m_lastError;

    static QString typeToString(QJsonValue::Type type) {
      switch(type) {
      case QJsonValue::Null:   return "Null";
      case QJsonValue::Bool:   return "Bool";
      case QJsonValue::Double: return "Double";
      case QJsonValue::String: return "String";
      case QJsonValue::Array:return "Array";
      case QJsonValue::Object: return "Object";
      default:               return "Unknown";
      }
    }
};2. 具体数据类实现示例

class UserProfile : public JsonSerializable {
public:
    // 必须字段
    QString username;
    QString email;
    int age = 0;

    // 可选字段
    QString phoneNumber;
    QDateTime registrationDate;

protected:
    bool toJson(QJsonObject &json) const override {
      // 验证数据有效性
      if (username.isEmpty() ||
            !email.contains('@') ||
            age < 0)
      {
            setError("Invalid user data");
            return false;
      }

      // 序列化必须字段
      json["username"] = username;
      json["email"] = email;
      json["age"] = age;

      // 序列化可选字段
      if (!phoneNumber.isEmpty())
            json["phone"] = phoneNumber;
      if (registrationDate.isValid())
            json["reg_date"] = registrationDate.toString(Qt::ISODate);

      return true;
    }

    bool fromJson(const QJsonObject &json) override {
      // 验证必须字段
      if (!validateField(json, "username", QJsonValue::String) ||
            !validateField(json, "email", QJsonValue::String) ||
            !validateField(json, "age", QJsonValue::Double))
      {
            return false;
      }

      // 解析必须字段
      username = json["username"].toString();
      email = json["email"].toString();
      age = json["age"].toInt();

      // 检查有效性
      if (username.isEmpty()) {
            setError("Username cannot be empty");
            return false;
      }
      if (!email.contains('@')) {
            setError("Invalid email format");
            return false;
      }
      if (age < 0) {
            setError("Age cannot be negative");
            return false;
      }

      // 解析可选字段
      if (json.contains("phone")) {
            if (json["phone"].type() != QJsonValue::String) {
                setError("Invalid phone number format");
                return false;
            }
            phoneNumber = json["phone"].toString();
      }

      if (json.contains("reg_date")) {
            if (!json["reg_date"].isString()) {
                setError("Invalid registration date format");
                return false;
            }
            registrationDate = QDateTime::fromString(
                json["reg_date"].toString(),
                Qt::ISODate
            );
            if (!registrationDate.isValid()) {
                setError("Malformed registration date");
                return false;
            }
      }

      return true;
    }
};3. 增强的错误处理拓展

class SafeJsonConverter {
public:
    // 带详细错误信息的泛型转换接口
    template<typename T>
    static bool fromJson(const QByteArray &jsonData, T &obj) {
      static_assert(std::is_base_of_v<JsonSerializable, T>,
                     "T must inherit from JsonSerializable");

      if (!obj.deserialize(jsonData)) {
            m_lastGlobalError = obj.lastError();
            return false;
      }
      return true;
    }

    template<typename T>
    static QByteArray toJson(const T &obj, bool *ok = nullptr) {
      static_assert(std::is_base_of_v<JsonSerializable, T>,
                     "T must inherit from JsonSerializable");

      QByteArray result;
      bool success = obj.serialize(result);
      if (ok) *ok = success;
      if (!success) m_lastGlobalError = obj.lastError();
      return result;
    }

    static QString lastError() { return m_lastGlobalError; }

private:
    inline static QString m_lastGlobalError;
};4. 使用示例及错误处理

int main() {    // 序列化测试    UserProfile user;    user.username = "john_doe";    user.email = "john@example.com";    user.age = 30;    user.phoneNumber = "+123456789";      QByteArray jsonData;    if (!user.serialize(jsonData)) {      qCritical()
页: [1]
查看完整版本: Qt中使用QJsonDocument实现安全的JSON序列化/反序列化方案,包含详细的错误处理机制