json数据解析,这是很常见的功能需求。c语言里有有名的cJSON库可用,当然c++里也可以直接用或者做个封装。但是可用不代表着就好用。有些情况下我们拿c++做开发而不是选择c,不就是为了开发上高效,维护上方便,可以做一些大项目么。
这里分享下封装的c++的好用的json解析库,不是原创。从OpenHarmony源码里摘出来的,所以可以放心用。直接学习优秀的开源项目代码好处多多,有时候是看书本学不来的。
【资料图】
摘自开源鸿蒙系统源码的JSUI框架代码。开源鸿蒙应用使用js开发,运行效率不用担心是因为框架使用的还是c++。
c++自从c++11标准之后真是焕然一新,使用变得简单且更好用了。从这个json解析源码里就能看出来一些:如使用了auto,lambda,智能指针等,智能指针的使用使得不用担心什么时候new的忘了释放掉这个心智负担,后续想new的地方要优先考虑使用智能指针。
条款21里有一条:尽量使用std::make_unique和std::make_shared而不直接使用new(《EffectiveModernC++》一书)。
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++PrimerFifthEdition中文版一书):
这个json解析类的源码里,至少用到了c++14及以上的特性(从std::make_unique这个智能指针可看出),若你的工具链版本低可能不行。
gcc工具链从4.7.0之后开始支持c++11标准。GCC4.8.1完全支持c++11核心部分,对应的glibc为2.17,gcc4.9支持c++11正则表达式。gcc从哪个版本之后开始支持c++14?好像是GCCv6.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"namespaceOHOS::Ace{JsonValue::JsonValue(JsonObject*object):object_(object){}JsonValue::JsonValue(JsonObject*object,boolisRoot):object_(object),isRoot_(isRoot){}JsonValue::~JsonValue{if(object_!=nullptr&&isRoot_){cJSON_Delete(object_);}object_=nullptr;}boolJsonValue::IsBoolconst{returncJSON_IsBool(object_);}boolJsonValue::IsNumberconst{returncJSON_IsNumber(object_);}boolJsonValue::IsStringconst{returncJSON_IsString(object_);}boolJsonValue::IsArrayconst{returncJSON_IsArray(object_);}boolJsonValue::IsObjectconst{returncJSON_IsObject(object_);}boolJsonValue::IsValidconst{return(object_!=nullptr)&&!cJSON_IsInvalid(object_);}boolJsonValue::IsNullconst{return(object_==nullptr)||cJSON_IsNull(object_);}boolJsonValue::Contains(conststd::string&key)const{returncJSON_HasObjectItem(object_,key.c_str);}boolJsonValue::GetBoolconst{returncJSON_IsTrue(object_)!=0;}boolJsonValue::GetBool(conststd::string&key,booldefaultValue)const{if(Contains(key)&&GetValue(key)->IsBool){returnGetValue(key)->GetBool;}returndefaultValue;}int32_tJsonValue::GetIntconst{returnstatic_cast((object_==nullptr)?0:object_->valuedouble);}uint32_tJsonValue::GetUIntconst{returnstatic_cast((object_==nullptr)?0:object_->valuedouble);}doubleJsonValue::GetDoubleconst{return(object_==nullptr)?0.0:object_->valuedouble;}doubleJsonValue::GetDouble(conststd::string&key,doubledefaultVal)const{autovalue=GetValue(key);if(value&&value->IsNumber){returnvalue->GetDouble;}returndefaultVal;}std::stringJsonValue::GetStringconst{return((object_==nullptr)||(object_->valuestring==nullptr))?"":std::string(object_->valuestring);}std::unique_ptrJsonValue::GetNextconst{if(object_==nullptr){returnstd::make_unique(nullptr);}returnstd::make_unique(object_->next);}std::unique_ptrJsonValue::GetChildconst{if(object_==nullptr){returnstd::make_unique(nullptr);}returnstd::make_unique(object_->child);}std::stringJsonValue::GetKeyconst{return((object_==nullptr)||(object_->string==nullptr))?"":std::string(object_->string);}std::unique_ptrJsonValue::GetValue(conststd::string&key)const{returnstd::make_unique(cJSON_GetObjectItem(object_,key.c_str));}std::unique_ptrJsonValue::GetObject(conststd::string&key)const{if(Contains(key)&&GetValue(key)->IsObject){returnGetValue(key);}returnstd::make_unique;}int32_tJsonValue::GetArraySizeconst{returncJSON_GetArraySize(object_);}std::unique_ptrJsonValue::GetArrayItem(int32_tindex)const{returnstd::make_unique(cJSON_GetArrayItem(object_,index));}boolJsonValue::Put(constchar*key,constchar*value){if(!value||!key){returnfalse;}cJSON*child=cJSON_CreateString(value);if(child==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,child);returntrue;}constJsonObject*JsonValue::GetJsonObjectconst{returnobject_;}boolJsonValue::Put(constchar*key,conststd::unique_ptr&value){if(!value||!key){returnfalse;}cJSON*jsonObject=cJSON_Duplicate(value->GetJsonObject,true);if(jsonObject==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,jsonObject);returntrue;}//additemtoarrayboolJsonValue::Put(conststd::unique_ptr&value){if(!value){returnfalse;}cJSON*jsonObject=cJSON_Duplicate(value->GetJsonObject,true);if(jsonObject==nullptr){returnfalse;}cJSON_AddItemToArray(object_,jsonObject);returntrue;}boolJsonValue::Put(constchar*key,size_tvalue){if(key==nullptr){returnfalse;}cJSON*child=cJSON_CreateNumber(static_cast(value));if(child==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,child);returntrue;}boolJsonValue::Put(constchar*key,int32_tvalue){if(key==nullptr){returnfalse;}cJSON*child=cJSON_CreateNumber(static_cast(value));if(child==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,child);returntrue;}boolJsonValue::Put(constchar*key,doublevalue){if(key==nullptr){returnfalse;}cJSON*child=cJSON_CreateNumber(value);if(child==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,child);returntrue;}boolJsonValue::Put(constchar*key,boolvalue){if(key==nullptr){returnfalse;}cJSON*child=cJSON_CreateBool(value);if(child==nullptr){returnfalse;}cJSON_AddItemToObject(object_,key,child);returntrue;}boolJsonValue::Replace(constchar*key,constchar*value){if((value==nullptr)||(key==nullptr)){returnfalse;}cJSON*child=cJSON_CreateString(value);if(child==nullptr){returnfalse;}if(!cJSON_ReplaceItemInObject(object_,key,child)){cJSON_Delete(child);returnfalse;}returntrue;}boolJsonValue::Replace(constchar*key,int32_tvalue){if(key==nullptr){returnfalse;}cJSON*child=cJSON_CreateNumber(static_cast(value));if(child==nullptr){returnfalse;}if(!cJSON_ReplaceItemInObject(object_,key,child)){cJSON_Delete(child);returnfalse;}returntrue;}boolJsonValue::Replace(constchar*key,conststd::unique_ptr&value){if((value==nullptr)||(key==nullptr)){returnfalse;}cJSON*jsonObject=cJSON_Duplicate(value->GetJsonObject,true);if(jsonObject==nullptr){returnfalse;}if(!cJSON_ReplaceItemInObject(object_,key,jsonObject)){cJSON_Delete(jsonObject);returnfalse;}returntrue;}boolJsonValue::Delete(constchar*key){if(key==nullptr){returnfalse;}cJSON_DeleteItemFromObject(object_,key);returntrue;}std::stringJsonValue::ToString{std::stringresult;if(!object_){returnresult;}//Itisnull-terminated.char*unformatted=cJSON_PrintUnformatted(object_);if(unformatted!=nullptr){result=unformatted;cJSON_free(unformatted);}returnresult;}std::stringJsonValue::GetString(conststd::string&key,conststd::string&defaultVal)const{autovalue=GetValue(key);if(value&&value->IsString){returnvalue->GetString;}returndefaultVal;}int32_tJsonValue::GetInt(conststd::string&key,int32_tdefaultVal)const{autovalue=GetValue(key);if(value&&value->IsNumber){returnvalue->GetInt;}returndefaultVal;}uint32_tJsonValue::GetUInt(conststd::string&key,uint32_tdefaultVal)const{autovalue=GetValue(key);if(value&&value->IsNumber){returnvalue->GetUInt;}returndefaultVal;}std::unique_ptrJsonUtil::ParseJsonData(constchar*data,constchar**parseEnd){returnstd::make_unique(cJSON_ParseWithOpts(data,parseEnd,true),true);}std::unique_ptrJsonUtil::ParseJsonString(conststd::string&content,constchar**parseEnd){returnParseJsonData(content.c_str,parseEnd);}std::unique_ptrJsonUtil::Create(boolisRoot){returnstd::make_unique(cJSON_CreateObject,isRoot);}std::unique_ptrJsonUtil::CreateArray(boolisRoot){returnstd::make_unique(cJSON_CreateArray,isRoot);}}//namespaceOHOS::Ace
#ifndefFOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H#defineFOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H#include#include#include"base/utils/macros.h"structcJSON;namespaceOHOS::Ace{usingJsonObject=cJSON;classACE_FORCE_EXPORTJsonValuefinal{public:JsonValue=default;explicitJsonValue(JsonObject*object);JsonValue(JsonObject*object,boolisRoot);~JsonValue;//checkfunctionsboolIsBoolconst;boolIsNumberconst;boolIsStringconst;boolIsArrayconst;boolIsObjectconst;boolIsValidconst;boolIsNullconst;boolContains(conststd::string&key)const;//getfunctionsboolGetBoolconst;boolGetBool(conststd::string&key,booldefaultValue=false)const;int32_tGetIntconst;int32_tGetInt(conststd::string&key,int32_tdefaultVal=0)const;uint32_tGetUIntconst;uint32_tGetUInt(conststd::string&key,uint32_tdefaultVal=0)const;doubleGetDoubleconst;doubleGetDouble(conststd::string&key,doubledefaultVal=0.0)const;std::stringGetStringconst;std::stringGetString(conststd::string&key,conststd::string&defaultVal="")const;std::unique_ptrGetNextconst;std::unique_ptrGetChildconst;std::stringGetKeyconst;std::unique_ptrGetValue(conststd::string&key)const;std::unique_ptrGetObject(conststd::string&key)const;int32_tGetArraySizeconst;std::unique_ptrGetArrayItem(int32_tindex)const;constJsonObject*GetJsonObjectconst;//putfunctionsboolPut(constchar*key,constchar*value);boolPut(constchar*key,size_tvalue);boolPut(constchar*key,int32_tvalue);boolPut(constchar*key,doublevalue);boolPut(constchar*key,boolvalue);boolPut(constchar*key,conststd::unique_ptr&value);boolPut(conststd::unique_ptr&value);//replacefunctionsboolReplace(constchar*key,constchar*value);boolReplace(constchar*key,int32_tvalue);boolReplace(constchar*key,conststd::unique_ptr&value);//deletefunctionsboolDelete(constchar*key);//serializestd::stringToString;private:JsonObject*object_=nullptr;boolisRoot_=false;};classACE_EXPORTJsonUtilfinal{public:JsonUtil=delete;~JsonUtil=delete;staticstd::unique_ptrParseJsonData(constchar*data,constchar**parseEnd=nullptr);staticstd::unique_ptrParseJsonString(conststd::string&content,constchar**parseEnd=nullptr);staticstd::unique_ptrCreate(boolisRoot);staticstd::unique_ptrCreateArray(boolisRoot);};}//namespaceOHOS::Ace#endif//FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H
使用方法,如以下代码片段,定义了一个右值引用actionEventHandler,使用了lambda表达式写法,c++新语法用着就是美:
//actioneventhadnlerauto&&actionEventHandler=[this](conststd::string&action){LOGI("onActioncalledtoeventhandler");autoeventAction=JsonUtil::ParseJsonString(action);autobundleName=eventAction->GetValue("bundleName");autoabilityName=eventAction->GetValue("abilityName");autoparams=eventAction->GetValue("params");autobundle=bundleName->GetString;autoability=abilityName->GetString;LOGI("bundle:%{public}sability:%{public}s,params:%{public}s",bundle.c_str,ability.c_str,params->GetString.c_str);if(bundle.empty||ability.empty){LOGE("actionabilityorbundleisempty");return;}AAFwk::Wantwant;want.SetElementName(bundle,ability);this->StartAbility(want);};
关键词: