2022-05-03 03:56:07 +00:00
|
|
|
|
|
|
|
#include "json.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2022-07-18 08:56:03 +00:00
|
|
|
#if defined(WIN32) || defined(_WIN64)
|
2022-05-03 03:56:07 +00:00
|
|
|
#define bzero(b, s) memset(b, 0, s)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
json::json(char* json_txt) : obj_(0), cur_child_(0)
|
|
|
|
{
|
|
|
|
attach_text(json_txt);
|
|
|
|
}
|
|
|
|
json::~json()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string json::to_string(cJSON* root)
|
|
|
|
{
|
|
|
|
char* txt = cJSON_Print(root);
|
|
|
|
std::string ret(txt ? txt : "");
|
|
|
|
|
|
|
|
if (txt)
|
|
|
|
free(txt);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
std::string json::get_value_as_string(cJSON* root, bool integer)
|
|
|
|
{
|
|
|
|
std::string ret("");
|
|
|
|
|
|
|
|
switch (root->type)
|
|
|
|
{
|
|
|
|
case cJSON_False:
|
|
|
|
ret = "false";
|
|
|
|
break;
|
|
|
|
case cJSON_True:
|
|
|
|
ret = "true";
|
|
|
|
break;
|
|
|
|
case cJSON_NULL:
|
|
|
|
ret = "null";
|
|
|
|
break;
|
|
|
|
case cJSON_Number:
|
|
|
|
{
|
|
|
|
char buf[40];
|
|
|
|
if (integer)
|
|
|
|
sprintf(buf, "%d", root->valueint);
|
|
|
|
else
|
|
|
|
sprintf(buf, "%f", root->valuedouble);
|
|
|
|
ret = buf;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cJSON_String:
|
|
|
|
if (root->valuestring)
|
|
|
|
ret = root->valuestring;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = json::to_string(root);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON* json::find_child(cJSON *parent, const char* child_name)
|
|
|
|
{
|
|
|
|
if (!parent)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cJSON *child = parent->child;
|
|
|
|
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
if (child->string && strcmp(child->string, child_name) == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
child = child->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
cJSON* json::find(const char* path)
|
|
|
|
{
|
|
|
|
cJSON *found = obj_;
|
|
|
|
|
|
|
|
if (path && *path)
|
|
|
|
{
|
|
|
|
std::string all(path);
|
|
|
|
char *cur = strtok(&all[0], "/");
|
|
|
|
|
|
|
|
while (cur)
|
|
|
|
{
|
|
|
|
found = find_child(found, cur);
|
|
|
|
if (!found)
|
|
|
|
break;
|
|
|
|
|
|
|
|
cur = strtok(0, "/");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool json::attach_text(char* json_txt)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
obj_ = cJSON_Parse(json_txt);
|
|
|
|
|
|
|
|
return obj_ != 0;
|
|
|
|
}
|
|
|
|
bool json::attach_cjson(cJSON* cjson)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
if (cjson)
|
|
|
|
{
|
|
|
|
std::string txt(json::to_string(cjson));
|
|
|
|
if (txt.length())
|
|
|
|
obj_ = cJSON_Parse(txt.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj_ != 0;
|
|
|
|
}
|
|
|
|
void json::clear(void)
|
|
|
|
{
|
|
|
|
if (obj_)
|
|
|
|
{
|
|
|
|
cJSON_Delete(obj_);
|
|
|
|
obj_ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string json::to_string(void)
|
|
|
|
{
|
|
|
|
if (obj_)
|
|
|
|
return json::to_string(obj_);
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool json::get_value(const char* key, bool& val)
|
|
|
|
{
|
|
|
|
cJSON* obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (obj->type == cJSON_True)
|
|
|
|
val = true;
|
|
|
|
else if (obj->type == cJSON_False)
|
|
|
|
val = false;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_value(const char* key, int& val)
|
|
|
|
{
|
|
|
|
cJSON* obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (obj->type != cJSON_Number)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
val = obj->valueint;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_value(const char* key, double& val)
|
|
|
|
{
|
|
|
|
cJSON *obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (obj->type != cJSON_Number)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
val = obj->valuedouble;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_value(const char* key, std::string& val)
|
|
|
|
{
|
|
|
|
cJSON *obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (obj->type != cJSON_String)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
val = obj->valuestring ? obj->valuestring : "";
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_value(const char* key, json*& val)
|
|
|
|
{
|
|
|
|
cJSON *obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
val = new json();
|
|
|
|
if (!val->attach_cjson(obj))
|
|
|
|
{
|
|
|
|
delete val;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_value_as_string(const char* key, std::string& val, bool integer)
|
|
|
|
{
|
|
|
|
cJSON* obj = find(key);
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
val = json::get_value_as_string(obj, integer);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::get_as_array(const char* key, std::vector<std::string>& val)
|
|
|
|
{
|
|
|
|
cJSON *obj = find(key);
|
|
|
|
|
|
|
|
val.clear();
|
|
|
|
if (obj && obj->type == cJSON_Array)
|
|
|
|
{
|
|
|
|
cJSON *child = obj->child;
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
if (child->type == cJSON_Number)
|
|
|
|
{
|
|
|
|
char buf[40];
|
|
|
|
sprintf(buf, "%d", child->valueint);
|
|
|
|
val.push_back(buf);
|
|
|
|
}
|
|
|
|
else if (child->type == cJSON_String)
|
|
|
|
val.push_back(child->valuestring ? child->valuestring : "");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *text = cJSON_Print(child);
|
|
|
|
val.push_back(text);
|
|
|
|
free(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
child = child->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool json::first_child(std::string& val)
|
|
|
|
{
|
|
|
|
cur_child_ = obj_->child;
|
|
|
|
val = "";
|
|
|
|
if (cur_child_)
|
|
|
|
{
|
|
|
|
val = json::get_value_as_string(cur_child_);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool json::next_child(std::string& val)
|
|
|
|
{
|
|
|
|
if (cur_child_)
|
|
|
|
cur_child_ = cur_child_->next;
|
|
|
|
|
|
|
|
val = "";
|
|
|
|
if (cur_child_)
|
|
|
|
{
|
|
|
|
val = json::get_value_as_string(cur_child_);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool json::set_value(const char* key, bool val)
|
|
|
|
{
|
|
|
|
cJSON* ele = this->find(key);
|
|
|
|
|
|
|
|
if (!ele)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ele->type == cJSON_String)
|
|
|
|
free(ele->valuestring);
|
|
|
|
|
|
|
|
if (val)
|
|
|
|
ele->type = cJSON_True;
|
|
|
|
else
|
|
|
|
ele->type = cJSON_False;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::set_value(const char* key, int val)
|
|
|
|
{
|
|
|
|
cJSON* ele = this->find(key);
|
|
|
|
|
|
|
|
if (!ele)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ele->type == cJSON_String)
|
|
|
|
free(ele->valuestring);
|
|
|
|
|
|
|
|
ele->type = cJSON_Number;
|
|
|
|
ele->valuedouble = ele->valueint = val;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::set_value(const char* key, double val)
|
|
|
|
{
|
|
|
|
cJSON* ele = this->find(key);
|
|
|
|
|
|
|
|
if (!ele)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ele->type == cJSON_String)
|
|
|
|
free(ele->valuestring);
|
|
|
|
|
|
|
|
ele->type = cJSON_Number;
|
|
|
|
ele->valuedouble = val;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool json::set_value(const char* key, std::string val)
|
|
|
|
{
|
|
|
|
cJSON* ele = this->find(key);
|
|
|
|
|
|
|
|
if (!ele)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ele->type == cJSON_String)
|
|
|
|
free(ele->valuestring);
|
|
|
|
ele->type = cJSON_String;
|
|
|
|
ele->valuestring = (char*)malloc(val.length() + 4);
|
|
|
|
bzero(ele->valuestring, val.length() + 4);
|
|
|
|
strcpy(ele->valuestring, val.c_str());
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|