/* Copyright (C) 2014 * swift project Community / Contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, * including this file, may be copied, modified, propagated, or distributed except according to the terms * contained in the LICENSE file. */ #include "json.h" #include "blackmisc/imageutils.h" #include "blackmisc/stringutils.h" #include #include #include #include using namespace BlackMisc; class QPixmap; const QJsonValue &operator >>(const QJsonValue &json, int &value) { value = json.toInt(); return json; } const QJsonValue &operator >>(const QJsonValue &json, qlonglong &value) { value = static_cast(json.toDouble()); return json; } const QJsonValue &operator >>(const QJsonValue &json, qulonglong &value) { value = static_cast(json.toDouble()); return json; } const QJsonValue &operator >>(const QJsonValue &json, uint &value) { value = static_cast(json.toInt()); return json; } const QJsonValue &operator >>(const QJsonValue &json, qint16 &value) { value = static_cast(json.toInt()); return json; } const QJsonValue &operator >>(const QJsonValue &json, QString &value) { value = json.toString(); return json; } const QJsonValue &operator >>(const QJsonValue &json, QStringList &value) { for (auto &&element : json.toArray()) { value << element.toString(); } return json; } const QJsonValue &operator >>(const QJsonValue &json, double &value) { value = json.toDouble(); return json; } const QJsonValue &operator >>(const QJsonValue &json, bool &value) { value = json.toBool(); return json; } const QJsonValue &operator >>(const QJsonValue &json, QDateTime &value) { value = QDateTime::fromString(json.toString()); return json; } const QJsonValue &operator >>(const QJsonValue &json, QPixmap &value) { const QString hex(json.toString()); BlackMisc::pngHexStringToPixmapRef(hex, value); return json; } const QJsonValue &operator >>(const QJsonValue &json, QByteArray &value) { const QString hex(json.toString()); value = BlackMisc::byteArrayFromHexString(hex); return json; } QJsonValueRef operator >>(QJsonValueRef json, int &value) { value = json.toInt(); return json; } QJsonValueRef operator >>(QJsonValueRef json, qlonglong &value) { value = static_cast(json.toDouble()); return json; } QJsonValueRef operator >>(QJsonValueRef json, qulonglong &value) { value = static_cast(json.toDouble()); return json; } QJsonValueRef operator >>(QJsonValueRef json, uint &value) { value = static_cast(json.toInt()); return json; } QJsonValueRef operator >>(QJsonValueRef json, qint16 &value) { value = static_cast(json.toInt()); return json; } QJsonValueRef operator >>(QJsonValueRef json, QString &value) { value = json.toString(); return json; } QJsonValueRef operator >>(QJsonValueRef json, QStringList &value) { for (auto &&element : json.toArray()) { value << element.toString(); } return json; } QJsonValueRef operator >>(QJsonValueRef json, double &value) { value = json.toDouble(); return json; } QJsonValueRef operator >>(QJsonValueRef json, bool &value) { value = json.toBool(); return json; } QJsonValueRef operator >>(QJsonValueRef json, QDateTime &value) { value = QDateTime::fromString(json.toString()); return json; } QJsonValueRef operator >>(QJsonValueRef json, QPixmap &value) { const QString hex(json.toString()); BlackMisc::pngHexStringToPixmapRef(hex, value); return json; } QJsonValueRef operator >>(QJsonValueRef json, QByteArray &value) { const QString hex(json.toString()); value = BlackMisc::byteArrayFromHexString(hex); return json; } QJsonArray &operator<<(QJsonArray &json, const int value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const qint16 value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const qlonglong value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const uint value) { json.append(QJsonValue(static_cast(value))); return json; } QJsonArray &operator<<(QJsonArray &json, const qulonglong value) { json.append(QJsonValue(static_cast(value))); return json; } QJsonArray &operator<<(QJsonArray &json, const QString &value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const double value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const bool value) { json.append(QJsonValue(value)); return json; } QJsonArray &operator<<(QJsonArray &json, const QDateTime &value) { json.append(QJsonValue(value.toString())); return json; } QJsonArray &operator<<(QJsonArray &json, const QPixmap &value) { QString pm(BlackMisc::pixmapToPngHexString(value)); json.append(QJsonValue(pm)); return json; } QJsonArray &operator<<(QJsonArray &json, const QByteArray &value) { QString pm(BlackMisc::byteArrayFromHexString(value)); json.append(QJsonValue(pm)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(static_cast(value.second))); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(static_cast(value.second))); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(QJsonArray::fromStringList(value.second))); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json.insert(value.first, QJsonValue(value.second.toString())); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { QString pm(BlackMisc::pixmapToPngHexString(value.second)); json.insert(value.first, pm); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { QString pm(BlackMisc::bytesToHexString(value.second)); json.insert(value.first, pm); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(static_cast(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(static_cast(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(QJsonArray::fromStringList(value.second)); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { json[value.first] = QJsonValue(value.second.toString()); return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { QString pm(BlackMisc::pixmapToPngHexString(value.second)); json[value.first] = pm; return json; } QJsonObject &operator<<(QJsonObject &json, const std::pair &value) { QString pm(BlackMisc::bytesToHexString(value.second)); json[value.first] = pm; return json; } namespace BlackMisc { namespace Json { QJsonObject jsonObjectFromString(const QString &json, bool acceptCacheFormat) { if (json.isEmpty()) { return QJsonObject();} const QJsonDocument jsonDoc(QJsonDocument::fromJson(json.toUtf8())); return acceptCacheFormat ? Json::unwrapCache(jsonDoc.object()) : jsonDoc.object(); // return acceptCacheFormat ? Json::swiftDataObjectValue(jsonDoc.object()) : jsonDoc.object(); } QString stringFromJsonObject(const QJsonObject &jsonObject, QJsonDocument::JsonFormat format) { const QJsonDocument doc(jsonObject); const QString strJson(doc.toJson(format)); return strJson; } QJsonArray jsonArrayFromString(const QString &json) { if (json.isEmpty()) { return QJsonArray();} const QJsonDocument jsonDoc(QJsonDocument::fromJson(json.toUtf8())); return jsonDoc.array(); } QJsonObject &appendJsonObject(QJsonObject &target, const QJsonObject &toBeAppended) { if (toBeAppended.isEmpty()) return target; const QStringList keys = toBeAppended.keys(); foreach (const QString &key, keys) { target.insert(key, toBeAppended.value(key)); } return target; } QJsonObject getIncrementalObject(const QJsonObject &previousObject, const QJsonObject ¤tObject) { QJsonObject incrementalObject = currentObject; for (const auto &key : previousObject.keys()) // clazy:exclude=range-loop { if (previousObject.value(key).isObject()) { auto child = getIncrementalObject(previousObject.value(key).toObject(), currentObject.value(key).toObject()); if (child.isEmpty()) incrementalObject.remove(key); else incrementalObject.insert(key, child); } else { if (currentObject.value(key) == previousObject.value(key)) incrementalObject.remove(key); } } return incrementalObject; } QJsonObject applyIncrementalObject(const QJsonObject &previousObject, const QJsonObject &incrementalObject) { QJsonObject currentObject = previousObject; for (const auto &key : incrementalObject.keys()) // clazy:exclude=range-loop { // If it is not an object, just insert the value if (!incrementalObject.value(key).isObject()) { currentObject.insert(key, incrementalObject.value(key)); } else { auto child = applyIncrementalObject(currentObject.value(key).toObject(), incrementalObject.value(key).toObject()); currentObject.insert(key, child); } } return currentObject; } bool looksLikeJson(const QString &json) { if (json.isEmpty()) { return false; } const QString t = json.trimmed(); return t.startsWith('{') && t.endsWith('}'); } bool looksLikeSwiftJson(const QString &json) { // further checks would go here return looksLikeJson(json); } bool looksLikeSwiftDataObjectJson(const QJsonObject &object) { // key // - type // - value if (object.size() != 1) { return false; } const QStringList keys = object.keys(); if (keys.size() != 1) { return false; } const QString key = keys.front(); const QJsonObject cacheObject = object.value(key).toObject(); return (cacheObject.contains("type") && cacheObject.contains("value")); } QJsonObject swiftDataObjectValue(const QString &jsonString) { const QJsonObject obj = jsonObjectFromString(jsonString); if (obj.isEmpty()) { return obj; } return swiftDataObjectValue(obj); } QJsonObject swiftDataObjectValue(const QJsonObject &object) { // key // - type // - value if (object.size() != 1) { return object; } // no cache format const QString key = object.keys().front(); const QJsonObject cacheObject = object.value(key).toObject(); if (cacheObject.contains("type") && cacheObject.contains("value")) { const QString type = cacheObject.value("type").toString(); // just to verify in debugger Q_UNUSED(type); return cacheObject.value("value").toObject(); } return object; } QJsonObject unwrapCache(const QJsonObject &object) { if (object.size() != 1) { return object; } // no cache format const QString key = object.keys().front(); const QJsonObject cacheObject = object.value(key).toObject(); if (cacheObject.contains("type") && cacheObject.contains("value")) { // return object in form type/value const QString type = cacheObject.value("type").toString(); // just to verify in debugger Q_UNUSED(type); return cacheObject; } return object; } QJsonObject unwrapCache(const QString &jsonString) { const QJsonObject obj = jsonObjectFromString(jsonString); if (obj.isEmpty()) { return obj; } return unwrapCache(obj); } bool looksLikeSwiftContainerJson(const QJsonObject &object) { // CContainerbase::convertFromJson return object.contains("containerbase"); } bool looksLikeSwiftTypeValuePairJson(const QJsonObject &object) { return (object.contains("type") && object.contains("value")); } bool looksLikeSwiftDbJson(const QJsonObject &object) { return (object.contains("data")); } QString firstJsonValueAsString(const QString &json) { static const QString empty; if (json.isEmpty()) { return empty; } const QJsonObject obj = jsonObjectFromString(json); return firstJsonValueAsString(obj); } QString firstJsonValueAsString(const QJsonObject &json) { static const QString empty; if (json.isEmpty()) { return empty; } const QStringList keys1 = json.keys(); if (keys1.isEmpty()) { return empty; } if (keys1.contains("value", Qt::CaseInsensitive)) { return json.value("value").toString(); } const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject(); return jsonLevel1.value("value").toString(); } QStringList firstJsonValueAsStringList(const QString &json) { static const QStringList empty; if (json.isEmpty()) { return empty; } const QJsonObject obj = jsonObjectFromString(json); return firstJsonValueAsStringList(obj); } int firstJsonValueAsInt(const QString &json, int defaultValue, bool *ok) { if (ok) { *ok = false; } if (json.isEmpty()) { return defaultValue; } const QJsonObject obj = jsonObjectFromString(json); return firstJsonValueAsInt(obj, defaultValue, ok); } int firstJsonValueAsInt(const QJsonObject &json, int defaultValue, bool *ok) { if (ok) { *ok = false; } if (json.isEmpty()) { return defaultValue; } const QStringList keys1 = json.keys(); if (keys1.isEmpty()) { return defaultValue; } if (keys1.contains("value", Qt::CaseInsensitive)) { if (ok) { *ok = true; } return json.value("value").toInt(defaultValue); } const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject(); if (!jsonLevel1.contains("value")) { return defaultValue; } if (ok) { *ok = true; } return jsonLevel1.value("value").toInt(defaultValue); } QStringList firstJsonValueAsStringList(const QJsonObject &json) { static const QStringList empty; if (json.isEmpty()) { return empty; } const QStringList keys1 = json.keys(); if (keys1.isEmpty()) { return empty; } if (keys1.contains("value", Qt::CaseInsensitive)) { return arrayToQStringList(json.value("value").toArray()); } const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject(); return arrayToQStringList(jsonLevel1.value("value").toArray()); } QStringList arrayToQStringList(const QJsonArray &array) { QStringList sl; if (array.isEmpty()) { return sl; } for (int i = 0; i < array.size(); i++) { if (!array.at(i).isString()) { continue; } sl.push_back(array.at(i).toString()); } return sl; } } // ns } // ns