c++好用的json解析类源码分享及简单使用

Posted 特立独行的猫a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++好用的json解析类源码分享及简单使用相关的知识,希望对你有一定的参考价值。

json数据解析,这是很常见的功能需求。c语言里有有名的cJSON库可用,当然c++里也可以直接用或者做个封装。但是可用不代表着就好用。有些情况下我们拿c++做开发而不是选择c,不就是为了开发上高效,维护上方便,可以做一些大项目么。

这里分享下封装的c++的好用的json解析库,不是原创。从OpenHarmony源码里摘出来的,所以可以放心用。直接学习优秀的开源项目代码好处多多,有时候是看书本学不来的。

摘自开源鸿蒙系统源码的JS UI框架代码。开源鸿蒙应用使用js开发,运行效率不用担心是因为框架使用的还是c++。

c++自从c++11标准之后真是焕然一新,使用变得简单且更好用了。从这个json解析源码里就能看出来一些:如使用了auto,lambda,智能指针等,智能指针的使用使得不用担心什么时候new的忘了释放掉这个心智负担,后续想new的地方要优先考虑使用智能指针。

条款21里有一条:尽量使用std::make_unique和std::make_shared而不直接使用new(《Effective Modern C++》一书)。

c++需要注意的地方之一就是对内存的管理,动态内存的使用经常会出现内存泄漏,或者产生引用非法内存的指针。

新的标准库提供了两种智能指针类型来管理动态对象:
(1)shared_ptr 允许多个指针指向同一个对象
(2)unique_ptr 独占所指向的对象
定义在memory头文件中,他们的作用在于会自动释放所指向的对象。

unique_ptr 是 C++ 11 提供的用于防止内存泄漏的智能指针中的一种实现,独享被管理对象指针所有权的智能指针。unique_ptr对象包装一个原始指针,并负责其生命周期。当该对象被销毁时,会在其析构函数中删除关联的原始指针。
unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用。

unique_ptr不能直接复制,必须使用std::move()转移其管理的指针,转移后原 unique_ptr 为空。

unique_ptr支持的操作(C++ Primer Fifth Edition 中文版一书):

这个json解析类的源码里,至少用到了c++14及以上的特性(从std::make_unique这个智能指针可看出),若你的工具链版本低可能不行。

gcc工具链从4.7.0之后开始支持c++11标准。GCC 4.8.1完全支持c++11核心部分,对应的glibc为2.17,gcc 4.9支持c++11正则表达式。gcc从哪个版本之后开始支持c++14?好像是GCC v6.1之后。

源码文件路径:code-v3.0-LTS\\OpenHarmony\\foundation\\ace\\ace_engine\\frameworks\\base\\json

json_util.cpp和json_util.h

其实还是对cJSON库的封装:

#include "base/json/json_util.h"

#include "cJSON.h"

namespace OHOS::Ace 

JsonValue::JsonValue(JsonObject* object) : object_(object) 

JsonValue::JsonValue(JsonObject* object, bool isRoot) : object_(object), isRoot_(isRoot) 

JsonValue::~JsonValue()

    if (object_ != nullptr && isRoot_) 
        cJSON_Delete(object_);
    
    object_ = nullptr;


bool JsonValue::IsBool() const

    return cJSON_IsBool(object_);


bool JsonValue::IsNumber() const

    return cJSON_IsNumber(object_);


bool JsonValue::IsString() const

    return cJSON_IsString(object_);


bool JsonValue::IsArray() const

    return cJSON_IsArray(object_);


bool JsonValue::IsObject() const

    return cJSON_IsObject(object_);


bool JsonValue::IsValid() const

    return (object_ != nullptr) && !cJSON_IsInvalid(object_);


bool JsonValue::IsNull() const

    return (object_ == nullptr) || cJSON_IsNull(object_);


bool JsonValue::Contains(const std::string& key) const

    return cJSON_HasObjectItem(object_, key.c_str());


bool JsonValue::GetBool() const

    return cJSON_IsTrue(object_) != 0;


bool JsonValue::GetBool(const std::string& key, bool defaultValue) const

    if (Contains(key) && GetValue(key)->IsBool()) 
        return GetValue(key)->GetBool();
    
    return defaultValue;


int32_t JsonValue::GetInt() const

    return static_cast<int32_t>((object_ == nullptr) ? 0 : object_->valuedouble);


uint32_t JsonValue::GetUInt() const

    return static_cast<uint32_t>((object_ == nullptr) ? 0 : object_->valuedouble);


double JsonValue::GetDouble() const

    return (object_ == nullptr) ? 0.0 : object_->valuedouble;


double JsonValue::GetDouble(const std::string& key, double defaultVal) const

    auto value = GetValue(key);
    if (value && value->IsNumber()) 
        return value->GetDouble();
    
    return defaultVal;


std::string JsonValue::GetString() const

    return ((object_ == nullptr) || (object_->valuestring == nullptr)) ? "" : std::string(object_->valuestring);


std::unique_ptr<JsonValue> JsonValue::GetNext() const

    if (object_ == nullptr) 
        return std::make_unique<JsonValue>(nullptr);
    
    return std::make_unique<JsonValue>(object_->next);


std::unique_ptr<JsonValue> JsonValue::GetChild() const

    if (object_ == nullptr) 
        return std::make_unique<JsonValue>(nullptr);
    
    return std::make_unique<JsonValue>(object_->child);


std::string JsonValue::GetKey() const

    return ((object_ == nullptr) || (object_->string == nullptr)) ? "" : std::string(object_->string);

std::unique_ptr<JsonValue> JsonValue::GetValue(const std::string& key) const

    return std::make_unique<JsonValue>(cJSON_GetObjectItem(object_, key.c_str()));


std::unique_ptr<JsonValue> JsonValue::GetObject(const std::string& key) const

    if (Contains(key) && GetValue(key)->IsObject()) 
        return GetValue(key);
    
    return std::make_unique<JsonValue>();


int32_t JsonValue::GetArraySize() const

    return cJSON_GetArraySize(object_);


std::unique_ptr<JsonValue> JsonValue::GetArrayItem(int32_t index) const

    return std::make_unique<JsonValue>(cJSON_GetArrayItem(object_, index));


bool JsonValue::Put(const char* key, const char* value)

    if (!value || !key) 
        return false;
    

    cJSON* child = cJSON_CreateString(value);
    if (child == nullptr) 
        return false;
    
    cJSON_AddItemToObject(object_, key, child);
    return true;


const JsonObject* JsonValue::GetJsonObject() const

    return object_;


bool JsonValue::Put(const char* key, const std::unique_ptr<JsonValue>& value)

    if (!value || !key) 
        return false;
    
    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
    if (jsonObject == nullptr) 
        return false;
    

    cJSON_AddItemToObject(object_, key, jsonObject);
    return true;


// add item to array
bool JsonValue::Put(const std::unique_ptr<JsonValue>& value)

    if (!value) 
        return false;
    
    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
    if (jsonObject == nullptr) 
        return false;
    

    cJSON_AddItemToArray(object_, jsonObject);
    return true;


bool JsonValue::Put(const char* key, size_t value)

    if (key == nullptr) 
        return false;
    

    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
    if (child == nullptr) 
        return false;
    
    cJSON_AddItemToObject(object_, key, child);
    return true;


bool JsonValue::Put(const char* key, int32_t value)

    if (key == nullptr) 
        return false;
    

    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
    if (child == nullptr) 
        return false;
    
    cJSON_AddItemToObject(object_, key, child);
    return true;


bool JsonValue::Put(const char* key, double value)

    if (key == nullptr) 
        return false;
    

    cJSON* child = cJSON_CreateNumber(value);
    if (child == nullptr) 
        return false;
    
    cJSON_AddItemToObject(object_, key, child);
    return true;


bool JsonValue::Put(const char* key, bool value)

    if (key == nullptr) 
        return false;
    

    cJSON* child = cJSON_CreateBool(value);
    if (child == nullptr) 
        return false;
    
    cJSON_AddItemToObject(object_, key, child);
    return true;


bool JsonValue::Replace(const char* key, const char* value)

    if ((value == nullptr) || (key == nullptr)) 
        return false;
    

    cJSON* child = cJSON_CreateString(value);
    if (child == nullptr) 
        return false;
    
    if (!cJSON_ReplaceItemInObject(object_, key, child)) 
        cJSON_Delete(child);
        return false;
    
    return true;


bool JsonValue::Replace(const char* key, int32_t value)

    if (key == nullptr) 
        return false;
    

    cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
    if (child == nullptr) 
        return false;
    
    if (!cJSON_ReplaceItemInObject(object_, key, child)) 
        cJSON_Delete(child);
        return false;
    
    return true;


bool JsonValue::Replace(const char* key, const std::unique_ptr<JsonValue>& value)

    if ((value == nullptr) || (key == nullptr)) 
        return false;
    
    cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
    if (jsonObject == nullptr) 
        return false;
    

    if (!cJSON_ReplaceItemInObject(object_, key, jsonObject)) 
        cJSON_Delete(jsonObject);
        return false;
    
    return true;


bool JsonValue::Delete(const char* key)

    if (key == nullptr) 
        return false;
    
    cJSON_DeleteItemFromObject(object_, key);
    return true;


std::string JsonValue::ToString()

    std::string result;
    if (!object_) 
        return result;
    

    // It is null-terminated.
    char* unformatted = cJSON_PrintUnformatted(object_);
    if (unformatted != nullptr) 
        result = unformatted;
        cJSON_free(unformatted);
    
    return result;


std::string JsonValue::GetString(const std::string& key, const std::string& defaultVal) const

    auto value = GetValue(key);
    if (value && value->IsString()) 
        return value->GetString();
    
    return defaultVal;


int32_t JsonValue::GetInt(const std::string& key, int32_t defaultVal) const

    auto value = GetValue(key);
    if (value && value->IsNumber()) 
        return value->GetInt();
    
    return defaultVal;


uint32_t JsonValue::GetUInt(const std::string& key, uint32_t defaultVal) const

    auto value = GetValue(key);
    if (value && value->IsNumber()) 
        return value->GetUInt();
    
    return defaultVal;


std::unique_ptr<JsonValue> JsonUtil::ParseJsonData(const char* data, const char** parseEnd)

    return std::make_unique<JsonValue>(cJSON_ParseWithOpts(data, parseEnd, true), true);


std::unique_ptr<JsonValue> JsonUtil::ParseJsonString(const std::string& content, const char** parseEnd)

    return ParseJsonData(content.c_str(), parseEnd);


std::unique_ptr<JsonValue> JsonUtil::Create(bool isRoot)

    return std::make_unique<JsonValue>(cJSON_CreateObject(), isRoot);


std::unique_ptr<JsonValue> JsonUtil::CreateArray(bool isRoot)

    return std::make_unique<JsonValue>(cJSON_CreateArray(), isRoot);


 // namespace OHOS::Ace
#ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H

#include <memory>
#include <string>

#include "base/utils/macros.h"

struct cJSON;

namespace OHOS::Ace 

using JsonObject = cJSON;

class ACE_FORCE_EXPORT JsonValue final 
public:
    JsonValue() = default;
    explicit JsonValue(JsonObject* object);
    JsonValue(JsonObject* object, bool isRoot);
    ~JsonValue();

    // check functions
    bool IsBool() const;
    bool IsNumber() const;
    bool IsString() const;
    bool IsArray() const;
    bool IsObject() const;
    bool IsValid() const;
    bool IsNull() const;
    bool Contains(const std::string& key) const;

    // get functions
    bool GetBool() const;
    bool GetBool(const std::string& key, bool defaultValue = false) const;
    int32_t GetInt() const;
    int32_t GetInt(const std::string& key, int32_t defaultVal = 0) const;
    uint32_t GetUInt() const;
    uint32_t GetUInt(const std::string& key, uint32_t defaultVal = 0) const;
    double GetDouble() const;
    double GetDouble(const std::string& key, double defaultVal = 0.0) const;
    std::string GetString() const;
    std::string GetString(const std::string& key, const std::string& defaultVal = "") const;

    std::unique_ptr<JsonValue> GetNext() const;
    std::unique_ptr<JsonValue> GetChild() const;
    std::string GetKey() const;
    std::unique_ptr<JsonValue> GetValue(const std::string& key) const;
    std::unique_ptr<JsonValue> GetObject(const std::string& key) const;
    int32_t GetArraySize() const;
    std::unique_ptr<JsonValue> GetArrayItem(int32_t index) const;
    const JsonObject* GetJsonObject() const;

    // put functions
    bool Put(const char* key, const char* value);
    bool Put(const char* key, size_t value);
    bool Put(const char* key, int32_t value);
    bool Put(const char* key, double value);
    bool Put(const char* key, bool value);
    bool Put(const char* key, const std::unique_ptr<JsonValue>& value);
    bool Put(const std::unique_ptr<JsonValue>& value);

    // replace functions
    bool Replace(const char* key, const char* value);
    bool Replace(const char* key, int32_t value);
    bool Replace(const char* key, const std::unique_ptr<JsonValue>& value);

    // delete functions
    bool Delete(const char* key);

    // serialize
    std::string ToString();

private:
    JsonObject* object_ = nullptr;
    bool isRoot_ = false;
;

class ACE_EXPORT JsonUtil final 
public:
    JsonUtil() = delete;
    ~JsonUtil() = delete;
    static std::unique_ptr<JsonValue> ParseJsonData(const char* data, const char** parseEnd = nullptr);
    static std::unique_ptr<JsonValue> ParseJsonString(const std::string& content, const char** parseEnd = nullptr);
    static std::unique_ptr<JsonValue> Create(bool isRoot);
    static std::unique_ptr<JsonValue> CreateArray(bool isRoot);
;

 // namespace OHOS::Ace

#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H

使用方法,如以下代码片段,定义了一个右值引用actionEventHandler ,使用了lambda表达式写法,c++新语法用着就是美:

// action event hadnler
    auto&& actionEventHandler = [this] (const std::string& action) 
        LOGI("on Action called to event handler");

        auto eventAction = JsonUtil::ParseJsonString(action);
        auto bundleName = eventAction->GetValue("bundleName");
        auto abilityName = eventAction->GetValue("abilityName");
        auto params = eventAction->GetValue("params");
        auto bundle = bundleName->GetString();
        auto ability = abilityName->GetString();
        LOGI("bundle:%publics ability:%publics, params:%publics",
            bundle.c_str(), ability.c_str(), params->GetString().c_str());
        if (bundle.empty() || ability.empty()) 
            LOGE("action ability or bundle is empty");
            return;
        

        AAFwk::Want want;
        want.SetElementName(bundle, ability);
        this->StartAbility(want);
    ;

以上是关于c++好用的json解析类源码分享及简单使用的主要内容,如果未能解决你的问题,请参考以下文章

C++ JSON处理库 CJsonObject 的使用

源码分析cJSON库学习

c++11:nlohmann::json进阶使用使用basic_json模板类

分享自己写的JS版日期格式化和解析工具类,绝对好用!

C++文件操作详解,实用文件辅助类源码分享,建议收藏自用!

分享自己写的JS版日期格式化和解析工具类,绝对好用!(转自小名同学)