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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 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:%{public}s ability:%{public}s, params:%{public}s",
            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);
    };



相关文章
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
37 5
|
20天前
|
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
47 0
|
20天前
|
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
29 1
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
110 4
JSON数据解析实战:从嵌套结构到结构化表格
|
1月前
|
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
61 5
鸿蒙赋能智慧物流:AI类目标签技术深度解析与实践
在数字化浪潮下,物流行业面临变革,传统模式的局限性凸显。AI技术为物流转型升级注入动力。本文聚焦HarmonyOS NEXT API 12及以上版本,探讨如何利用AI类目标签技术提升智慧物流效率、准确性和成本控制。通过高效数据处理、实时监控和动态调整,AI技术显著优于传统方式。鸿蒙系统的分布式软总线技术和隐私保护机制为智慧物流提供了坚实基础。从仓储管理到运输监控再到配送优化,AI类目标签技术助力物流全流程智能化,提高客户满意度并降低成本。开发者可借助深度学习框架和鸿蒙系统特性,开发创新应用,推动物流行业智能化升级。
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
110 12
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等