JSON的c/c++实现版本很多,可是用起来总是感觉不是那么顺手,于是就把自己能用的所谓奇技淫巧全都使了出来,可是貌似还是不尽满意。不过还是贴出来,算是当个纪念吧。
#include <unordered_map>
#include <algorithm>
#include <sstream>
#include <vector>
#include <map>
typedef std::unordered_map<std::string,std::string> object_container;
namespace value_object_detail{
static const std::string string_type = "string";
static const std::string number_type = "number";
static const std::string bool_type = "bool";
static const std::string object_type = "object";
static const std::string array_type = "array";
static const std::string null_type = "null";
JSON数值实现类,用来尽可能的使得字符串数值和c/c++原生数据类型无缝集成
class json_value{
public:
json_value(object_container& inst,const std::string& key):
inst_(inst),preffix_(key)
{
}
json_value(const json_value& jv):inst_(jv.inst_),preffix_(jv.preffix_){
}
protected:
void set_meta_information(const std::string& key,int index = 0){
std::string& key_type = inst_[preffix_];
const char* assert_type = NULL;
std::stringstream ss;
if(!key.empty()){
ss << "object@" << key << ",";
assert_type = "array@";
}else{
ss << "array@" << index << ",";
assert_type = "object@";
}
std::string append_type = ss.str();
if(std::string::npos != key_type.find(assert_type)){
del();
inst_[preffix_] = append_type;
return;
}
//assign repeat
if(std::string::npos == key_type.find(append_type)){
key_type += append_type;
}
}
public:
json_value operator[](int i){
using namespace value_object_detail;
set_meta_information("",i);
std::stringstream ss;
ss << preffix_ << "." << i;
return json_value(inst_,ss.str());
}
json_value operator[](const std::string& key){
using namespace value_object_detail;
set_meta_information(key);
return json_value(inst_,key.empty() ? preffix_ : preffix_ + "." + key);
}
public:
std::string& operator*(){
return inst_[preffix_];
}
bool operator!()const{
return inst_.end() == inst_.find(preffix_);
}
public:
const std::string& str_value()const {
const static std::string ret;
object_container::const_iterator it = inst_.find(preffix_);
return inst_.end() == it ? ret : it->second;
}
const std::string& str_key()const {
return preffix_;
}
public:
const std::string& type_string()const{
const std::string& val = str_value();
if(val.empty()){
return null_type;
}
if(std::string::npos != val.find("array@")){
return array_type;
}
if(std::string::npos != val.find("object@")){
return object_type;
}
return number_type;
}
public:
template<class Fn>
void for_each(Fn f){
object_container::const_iterator it = inst_.find(preffix_);
const std::string& type = type_string();
if(inst_.end() == it || (array_type != type && object_type != type)){
return ;
}
std::string sub_key = "";
std::string::size_type posb = 0,pose = 0,posn = std::string::npos;
object_container::const_iterator sub_it;
for(posb = pose = 0;;posb += 1,pose += 1){
posb = it->second.find('@',posb);
pose = it->second.find(',',pose);
if(posn == posb || posn == pose){
break;
}
sub_key = it->second.substr(posb+1,pose - posb -1);
sub_it = inst_.find(preffix_ + "." + sub_key);
if(inst_.end() != sub_it){
f(sub_key,sub_it->second);
}else{
f(sub_key,"");
}
}
}
void del(){
const std::string& type = type_string();
if(array_type == type){
int i = 0;
for(json_value jv = this->operator[](i);!!jv;++i){
jv.del();
}