jsoncpp按寫入順序讀取

Linux袁浩發表於2024-05-17

jsoncpp按寫入順序讀取

在不修改jsoncpp原始碼的基礎上,按照寫入順序讀取,編寫JsonValue類派生自Json::Value。

jsonvalue.h

#ifndef JSONVALUE_H
#define JSONVALUE_H

#include <jsoncpp/json/json.h>

class JsonValue : public Json::Value
{
public:
    static inline Json::Value &toValue(JsonValue &value)
    {
        return *reinterpret_cast<Json::Value*>(&value);
    }
    static inline JsonValue &fromValue(Json::Value &value)
    {
        return *reinterpret_cast<JsonValue*>(&value);
    }
    static inline const Json::Value &toConstValue(const JsonValue &value)
    {
        return *reinterpret_cast<const Json::Value*>(&value);
    }
    static inline const JsonValue &fromConstValue(const Json::Value &value)
    {
        return *reinterpret_cast<const JsonValue*>(&value);
    }
public:
    JsonValue(Json::ValueType type = Json::ValueType::nullValue):Json::Value(type){}
    JsonValue(Int value):Json::Value(value){}
    JsonValue(UInt value):Json::Value(value){}
#if defined(JSON_HAS_INT64)
    JsonValue(Int64 value):Json::Value(value){}
    JsonValue(UInt64 value):Json::Value(value){}
#endif // if defined(JSON_HAS_INT64)
    JsonValue(double value):Json::Value(value){}
    JsonValue(const char* value):Json::Value(value){}
    JsonValue(const char* begin, const char* end):Json::Value(begin, end){}
    JsonValue(const Json::StaticString& value):Json::Value(value){}
    JsonValue(const JSONCPP_STRING& value):Json::Value(value){}///< Copy data() til size(). Embedded zeroes too.
#ifdef JSON_USE_CPPTL
    JsonValue(const CppTL::ConstString& value):Json::Value(value){}
#endif
    JsonValue(bool value):Json::Value(value){}
    JsonValue(const Json::Value& other):Json::Value(other){}
    JsonValue(const JsonValue& other):Json::Value(toConstValue(other)){}
#if JSON_HAS_RVALUE_REFERENCES
    JsonValue(JsonValue&& other):Json::Value(other){}
#endif
    JsonValue& operator=(JsonValue other) {return fromValue(Json::Value::operator=(toValue(other)));}
    void swap(Value& other){Json::Value::swap(other);}
    void swapPayload(Value& other){Json::Value::swapPayload(other);}
    Json::ValueType type() const{return Json::Value::type();}
    /// Compare payload only, not comments etc.
    bool operator<(const JsonValue& other) const{return Json::Value::operator<(other);}
    bool operator<=(const JsonValue& other) const{return Json::Value::operator<=(other);}
    bool operator>=(const JsonValue& other) const{return Json::Value::operator>=(other);}
    bool operator>(const JsonValue& other) const{return Json::Value::operator>(other);}
    bool operator==(const JsonValue& other) const{return Json::Value::operator==(other);}
    bool operator!=(const JsonValue& other) const{return Json::Value::operator!=(other);}
    int compare(const JsonValue& other) const{return Json::Value::compare(other);}
public:
    JsonValue& operator[](ArrayIndex index){return fromValue(Json::Value::operator[](index));}
    JsonValue& operator[](int index){return fromValue(Json::Value::operator[](index));}
    const JsonValue& operator[](ArrayIndex index) const{return fromConstValue(Json::Value::operator[](index));}
    const JsonValue& operator[](int index) const {return fromConstValue(Json::Value::operator[](index));}
    JsonValue get(ArrayIndex index, const JsonValue& defaultValue) const{return Json::Value::get(index, defaultValue);}
    JsonValue& append(const JsonValue& value){return fromValue(Json::Value::append(value));}
    const JsonValue& operator[](const char* key) const{return fromConstValue(Json::Value::operator[](key));}
    const JsonValue& operator[](const JSONCPP_STRING& key) const{return fromConstValue(Json::Value::operator[](key));}
    JsonValue get(const char* key, const JsonValue& defaultValue) const{return Json::Value::get(key, defaultValue);}
    JsonValue get(const char* begin, const char* end, const JsonValue& defaultValue) const{return Json::Value::get(begin, end, defaultValue);}
    JsonValue get(const JSONCPP_STRING& key, const JsonValue& defaultValue) const{return Json::Value::get(key, defaultValue);}
#ifdef JSON_USE_CPPTL
    JsonValue get(const CppTL::ConstString& key, const JsonValue& defaultValue) const{return Json::Value::get(key, defaultValue);}
#endif
    JsonValue const* find(char const* begin, char const* end) const {return reinterpret_cast<JsonValue const*>(Json::Value::find(begin, end));}
    JsonValue const* demand(char const* begin, char const* end){return reinterpret_cast<JsonValue const*>(Json::Value::demand(begin, end));}
    inline JsonValue& operator[](const JSONCPP_STRING& key){return JsonValue::operator[](key.c_str());}
    inline JsonValue& operator[](const Json::StaticString& key) {return JsonValue::operator[](key.c_str());}
#ifdef JSON_USE_CPPTL
  JsonValue& operator[](const CppTL::ConstString& key){return fromValue(Json::Value::operator[](key));};
  const JsonValue& operator[](const CppTL::ConstString& key) const{return fromValue(Json::Value::operator[](key));};
#endif
    JsonValue removeMember(const JSONCPP_STRING& key){return removeMember(key.c_str());}
    bool removeMember(JSONCPP_STRING const& key, JsonValue* removed){return removeMember(key.c_str(), removed);}
    bool removeMember(const char* begin, const char* end, JsonValue* removed) {return Json::Value::removeMember(std::string(begin, end - begin).c_str(), removed);}
    bool removeIndex(ArrayIndex i, JsonValue* removed) {return Json::Value::removeIndex(i, reinterpret_cast<Json::Value*>(removed));}
public:
    JsonValue& operator[](const char* key);
    Members getMemberNames() const;
    JsonValue removeMember(const char* key);
    bool removeMember(const char* key, JsonValue* removed);
public:
    static    std::string m_KeyWordQueueName;
};

#endif // JSONVALUE_H

jsonvalue.cpp

#include "jsonvalue.h"
std::string JsonValue::m_KeyWordQueueName = "#JsonValue#Members";

JsonValue& JsonValue::operator[](const char* key) {
    if(m_KeyWordQueueName != key)
    {
        if(isMember(m_KeyWordQueueName)) {
            Json::Value& object = Json::Value::operator[](m_KeyWordQueueName.c_str());
            if(object.isArray()) {
                int32_t bufPos = object.size();
                for(int32_t i = 0; i < bufPos; ++i) {
                    if(object[i] == key) {
                        return fromValue(Json::Value::operator[](key));
                    }
                }
                object[bufPos] = key;
            }
            else {
                if(!object.isArray()) Json::Value::operator[](0) = key;
            }
        } else {
            Json::Value::operator[](m_KeyWordQueueName)[0] = key;
        }
    }
    return fromValue(Json::Value::operator[](key));
}

JsonValue::Members JsonValue::getMemberNames() const
{
    JsonValue::Members cache;
    if(isMember(m_KeyWordQueueName)) {
        for(int i = 0; i < static_cast<int>(operator[](m_KeyWordQueueName).size()); ++i) {
            cache.push_back(operator[](m_KeyWordQueueName)[i].asString());
        }
    }
    return cache;
}

JsonValue JsonValue::removeMember(const char* key)
{
    if(m_KeyWordQueueName != key) {
        JsonValue::Members cache;
        bool flag = false;
        if(isMember(m_KeyWordQueueName)) {
            for(int i = 0; i < static_cast<int>(operator[](m_KeyWordQueueName).size()); ++i) {
                const auto &name = operator[](m_KeyWordQueueName)[i].asString();
                if(name == key) {
                    flag = true;
                } else {
                    cache.push_back(name);
                }
            }
        }
        if(flag) {
            Json::Value::removeMember(m_KeyWordQueueName, this);
            for(int i = 0; i < static_cast<int>(cache.size()); ++i) {
                Json::Value::operator[](m_KeyWordQueueName)[i] = cache[i];
            }
        }
    }
    return JsonValue(Json::Value::removeMember(key));
}

bool JsonValue::removeMember(const char* key, JsonValue* removed)
{
    if(m_KeyWordQueueName != key) {
        JsonValue::Members cache;
        bool flag = false;
        if(isMember(m_KeyWordQueueName)) {
            for(int i = 0; i < static_cast<int>(operator[](m_KeyWordQueueName).size()); ++i) {
                const auto &name = operator[](m_KeyWordQueueName)[i].asString();
                if(name == key) {
                    flag = true;
                } else {
                    cache.push_back(name);
                }
            }
        }
        if(flag) {
            Json::Value::removeMember(m_KeyWordQueueName, this);
            for(int i = 0; i < static_cast<int>(cache.size()); ++i) {
                Json::Value::operator[](m_KeyWordQueueName)[i] = cache[i];
            }
        }
    }
    return Json::Value::removeMember(key, reinterpret_cast<Json::Value*>(removed));
}

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include "jsonvalue.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    JsonValue root;
    constexpr bool shouldUseOldWay = false;
    int count = 0;
    root["className"] = "高一(3)班";
    root["teacher"]["name"] = "小王";
    root["teacher"]["age"] = 28;

    //陣列
    root["student"][count]["name"] = "張三";
    root["student"][count]["age"] = 15;
    root["student"][count]["friend"]["name"] = "大黃";
    root["student"][count]["friend"]["age"] = 3;
    ++count;
    root["student"][count]["name"] = "李四";
    root["student"][count]["age"] = 14;
    root["student"][count]["friend"]["name"] = "小黑";
    root["student"][count]["friend"]["age"] = 3;
    ++count;
    root["student"][count]["name"] = "王五";
    root["student"][count]["age"] = 13;
    root["student"][count]["friend"]["name"] = "大花";
    root["student"][count]["friend"]["age"] = 3;
    ++count;


    if (shouldUseOldWay) {
        Json::FastWriter writer;
        const std::string json_file = writer.write(root);
        qInfo() << json_file.c_str();
    } else {
        Json::StreamWriterBuilder builder;
        const std::string json_file = Json::writeString(builder, root);
        qInfo() << json_file.c_str();
    }

    return a.exec();
}

以派生類JsonValue代替基類Json::Value即可自動實現key值順序記錄,讀取時使用getMemberNames獲取到的key值陣列中的key值順序與寫入時相同。

相關文章