json解析器的代码实现

        设计一个KJSon类,支持从xx.json文件解析字符串和生成JSON序列化对象,并写入到xx.json文件中。

        关于json格式详情请看教程:JSON详细教程


基本功能:

  • 支持解析和生成以下数据类型:
  • 字符串
  • 整数
  • 浮点数
  • 布尔值
  • 空值(null)
  • 对象(嵌套JSON对象)
  • 数组(支持嵌套数组)

进阶功能

  • 支持动态键名 : 允许使用动态生成的键名进行键值对的添加和访问,支持运行时生成键名的场景。

待完善功能:

  • XML序列化格式支持: 扩展序列化功能,使其支持JSON序列化转为XML序列化
  • 多线程安全:确保对多线程环境中对JSON对象访问和修改不会产生竞争条件。
     KJson.h
  • #pragma once
    #include <string>
    #include <vector>
    #include <map>
    #include <unordered_map>
    #include <algorithm>
    #include<iostream>
    
    #define POS 1               //该数字为正
    #define UNKNOWNED 0         //该数字为正
    #define NEG -1              //该数字为正
    #define NOT_INITIAL -1      //该KJson未初始化
    #define KJson_NULL 0        //该KJson为空
    #define KJson_Bool 1
    #define KJson_Int 2
    #define KJson_Double 3
    #define KJson_String 4
    #define KJson_Array 5
    #define KJson_Object 6
    
    static const char* IgnoreSpace(const char* in)  //用来跳过json里的空格
    {
        while (in && *in && (unsigned char)*in <= 32)
            in++;
        return in;
    }
    std::string Tab(std::string str, int i)
    {
        std::string res;
        while (i--)
        {
            res += str;
        }
        return res;
    }
    static const unsigned char BOM[7] = 
    { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
    //实现的功能:支持符号[]和()访问,支持格式化文件输出,支持动态键值对,支持解析报错
    //不足:空间使用较大,使用了较多c风格字符串
    class KJson {
    public:
        KJson();
        KJson(const char* json);
        KJson(const std::string json);
        KJson& operator[](const std::string key);   //使用者需要是json对象,否则返回自己
        KJson& operator[](unsigned int i);          //使用者需要是json对象,否则返回自己
        std::string operator()(const std::string key);  //使用者需要是json对象或列表,否则提示错误
        std::string operator()(unsigned int i);     //使用者需要是json对象或列表,否则提示错误
        KJson& operator=(KJson& jj);
        KJson& operator=(KJson&& jj);
        KJson& operator=(std::string vstring);  //修改键值
        KJson& operator=(int vint);             //修改键值
        KJson& operator=(double vdouble);       //修改键值
        std::string to_string();    //将内容转化为格式化字符串
        void Clear();           //清空内容
        ~KJson();
        const char* analys(const char* json, const char** error_loc);
        const char* analys_object(const char* json, const char** error_loc);
        const char* analys_array(const char* json, const char** error_loc);
        const char* analys_string(const char* json, const char** error_loc);
        const char* analys_number(const char* json, const char** error_loc);
        int get_size();
        int get_type();
    
    private:
        const char* error_loc;  //用来存放解析的报错信息
        std::string key;    //该KJson的键名
        int type;   //类型
        int sign;   //如果是整型或者浮点型,标记正负
        union Data {
            std::string* vstring;
            int* vint;
            double* vdouble;
            bool* vbool;
            void* vnull; // 使用void*来表示null
        } data;
        mutable std::unordered_map<unsigned int, KJson*> mapJ_array;            //用来存储列表里的内容
        mutable std::unordered_map<std::string, KJson*> mapJ_object;            //用来存储列表里的内容
        void KJson_analys(const char* json, const char** error_loc);
    };
    KJson::KJson() :error_loc(NULL),type(NOT_INITIAL),sign(UNKNOWNED)
    {
        data.vstring = NULL;
        
    }
    KJson::KJson(const char* json):error_loc(NULL)
    {
        KJson_analys(json, &error_loc);
    }
    KJson::KJson(const std::string json):error_loc(NULL)
    {
        KJson_analys(json.c_str(), &error_loc);
    }
    void KJson::KJson_analys(const char* json, const char** error_loc)
    {
        analys(json, error_loc);
        if (*error_loc!=NULL)
        {
            std::cout << "在" <<std::endl<< *error_loc <<std::endl<< "处发生解析错误"<<std::endl;
            Clear();
        }
        return;
    }
    const char* KJson::analys( const char* json, const char** error_loc)
    {
        
        if(!json)
        {
            data.vstring = NULL;
            return 0;
        }
        if (!strncmp(json, "false", 5))
        {
            this->type = KJson_Bool;
            this->data.vbool = new bool(false);
            return json + 5;
        }
        if (!strncmp(json, "true", 4))
        {
            this->type = KJson_Bool;
            this->data.vbool = new bool(true);
            return json + 4;
        }
        if (!strncmp(json, "null", 4))
        {
            this->type = KJson_NULL;
            this->data.vnull = NULL;
            return json + 4;
        }
        if (*json == '{')	//对象
            return analys_object(json, error_loc);
        if (*json == '[')	//列表
            return analys_array(json, error_loc);
        if (*json == '\"')	//键值对的键名或者字符串类型键值
            return analys_string(json, error_loc);
        if (*json == '-' || (*json >= '0' && *json <= '9'))
            return analys_number(json, error_loc);
        *error_loc = json;
        return 0;
    }
    const char* KJson::analys_object(const char* json, const char** error_loc)
    {
        if (*json != '{')
        {
            *error_loc = json;
            return 0;
        }
        this->type = KJson_Object;
        json = IgnoreSpace(json + 1);
        if (*json == '}')return json + 1;//空的对象
        if (*json != '\"')
        {
            //std::cout << "wrong format!";
            *error_loc = json;
            return 0;
        }
        KJson* child = new KJson;
        if (!child)return 0;
        json= IgnoreSpace((*child).analys_string( IgnoreSpace(json), error_loc));//处理对象里第一个键值对的键名
        if (!json)return 0;
        child->key = *(child->data.vstring);
        delete child->data.vstring;
        child->data.vstring = NULL;
        mapJ_object.insert(std::pair<std::string, KJson*>(child->key, child));
        if (*json != ':')
        {
            *error_loc = json;
            return 0;
        }
        json = IgnoreSpace((*child).analys( IgnoreSpace(json + 1), error_loc));
        if (!json)return 0;
        while (*json == ',')
        {
            child = new KJson;
            json = IgnoreSpace((*child).analys(IgnoreSpace(json + 1), error_loc));
            if (!json)return 0;
            child->key = *(child->data.vstring);
            delete child->data.vstring;
            child->data.vstring = NULL;
            mapJ_object.insert(std::pair<std::string, KJson*>(child->key, child));
            if (*json != ':')
            {
                *error_loc = json;
                return 0;
            }
            json = IgnoreSpace((*child).analys(IgnoreSpace(json + 1), error_loc));
            
            if (!json)return 0;
    
    
        }
        if (*json == '}')return json + 1;
        *error_loc = json;
        return 0;
    }
    
    const char* KJson::analys_array(const char* json, const char** error_loc)
    {
        if (*json != '[')
        {
            *error_loc = json;
            return 0;
        }
        this->type = KJson_Array;
        json = IgnoreSpace(json + 1);
        if (*json == ']')return json + 1;
        KJson* child = new KJson;
        if (!child)return 0;
        unsigned int i = 0;
        json = IgnoreSpace((*child).analys(IgnoreSpace(json), error_loc));
        mapJ_array.insert(std::pair<unsigned int, KJson*>(i++, child));
        if (!json)return 0;
        while (*json == ',')
        {
            child = new KJson;
            if (!child)return 0;
            json = IgnoreSpace((*child).analys(IgnoreSpace(json + 1), error_loc));
            mapJ_array.insert(std::pair<unsigned int, KJson*>(i++, child));
            if (!json)return 0;
        }
        if (*json == ']')return json + 1;
        *error_loc = json;
        return 0;
    
    }
    const char* KJson::analys_number(const char* json, const char** error_loc)
    {
        long long num_int = 0;
        long double num_double = 0.0;
        double base = 0.0;
        double point = 0.1;
        int a = 0;	//记录小数点后面有多少位
        int s = 0;	//记录指数
        int signs = 1;	//记录指数正负
        this->sign = POS;	//初始默认为无符号数
        if (*json == '-')
        {
            this->sign = NEG;
            json++;
        }
        if (*json == '0')json++;
        while (*json >= '0' && *json <= '9')
        {
            num_int = (num_int * 10) + (*json++ - '0');
        }
        num_double = num_int;	//这里可能会丢失数据,需要改进
        if (*json == '.')
        {
            if (json[1] >= '0' && json[1] <= '9')
            {
                json++;
                base = num_double;
                do {
                    num_double += point * (*json - '0');
                    point *= 0.1;
                    base = (base * 10.0) + (*json - '0');
                    a--;
                    json++;
                } while (*json >= '0' && *json <= '9');
            }
            else {
                *error_loc = json;
                return 0;
            }
        }
        if (*json == 'e' || *json == 'E')
        {
            json++;
            if (*json == '+')json++;
            else if (*json == '-')
            {
                signs = -1;
                json++;
            }
            while (*json >= '0' && *json <= '9')
                s = (s * 10) + (*json++ - '0');
        }
        if (a == 0 && s == 0)	//这是一个整数
        {
            this->data.vint= new int(this->sign * num_int);
            this->type = KJson_Int;
        }
        else {
            if (s != 0)
            {
                num_double = this->sign * base * pow(10.0, (a + s * signs));
            }
            this->data.vdouble = new double( num_double);
            this->type = KJson_Double;
    
        }
        return json;
    }
    const char* KJson::analys_string(const char* json, const char** error_loc)
    {
        if (*json != '\"')
        {
            *error_loc = json;
            //std::cout << "not a string";
            return 0;
        }
        const char* json1 = json + 1;//用于读取双引号里的内容
        char* json2;
        char* json3;
        int len = 0;
        unsigned a1, a2;
        while (*json1 != '\"' && *json1 && ++len)//获得引号内容的真正长度
            if (*json1++ == '\\')
                json1++;
        json3 = (char*)malloc(len + 1);
        if (!json3)return 0;
        json1 = json + 1;
        json2 = json3;
        while (*json1 != '\"' && *json1)
        {
            if (*json != '\\')
                *json2++ = *json1++;
            else
            {
                json++;
                switch (*json)
                {
                case 'b':
                    *json2++ = '\b';
                    break;
                case 'f':
                    *json2++ = '\f';
                    break;
                case 'n':
                    *json2++ = '\n';
                    break;
                case 'r':
                    *json2++ = '\r';
                    break;
                case 't':
                    *json2++ = '\t';
                    break;
                case 'u':	//经典的UTF8转换
                    sscanf_s(json1 + 1, "%4x", &a1);
                    json1 += 4;
    
                    if ((a1 >= 0xDC00 && a1 <= 0xDFFF) || a1 == 0)
                        break;	//非法
    
                    if (a1 >= 0xD800 && a1 <= 0xDBFF)
                    {
                        if (json1[1] != '\\' || json1[2] != 'u')
                            break;
                        sscanf_s(json1 + 3, "%4x", &a2);
                        json1 += 6;
                        if (a2 < 0xDC00 || a2 > 0xDFFF)
                            break;
                        a1 = 0x10000 | ((a1 & 0x3FF) << 10) | (a2 & 0x3FF);
                    }
    
                    len = 4;
                    if (a1 < 0x80)
                        len = 1;
                    else if (a1 < 0x800)
                        len = 2;
                    else if (a1 < 0x10000)
                        len = 3;
                    json2 += len;
    
                    switch (len)
                    {
                    case 4:
                        *--json2 = ((a1 | 0x80) & 0xBF);
                        a1 >>= 6;
                    case 3:
                        *--json2 = ((a1 | 0x80) & 0xBF);
                        a1 >>= 6;
                    case 2:
                        *--json2 = ((a1 | 0x80) & 0xBF);
                        a1 >>= 6;
                    case 1:
                        *--json2 = (a1 | BOM[len]);
                    }
                    json2 += len;
                    break;
                default:
                    *json2++ = *json1;
                    break;
                }
                json1++;
            }
        }
        *json2 = 0;
        if (*json1 == '\"')
            json1++;
        this->data.vstring = new std::string((std::string)json3);
        this->type = KJson_String;
        return json1;	//此时json1已经是越过了要处理的一串字符了
    }
    void KJson::Clear()
    {
        if (this->type == NOT_INITIAL)return;
        if(this->type==KJson_String)
            if(!this->data.vstring)
            {
                delete this->data.vstring;
                return;
            }
        if (this->type == KJson_Int)
            if (!this->data.vint)
            {
                delete this->data.vint;
                return;
            }
        if (this->type == KJson_Double)
            if (!this->data.vdouble)
            {
                delete this->data.vdouble;
                return;
            }
        if (this->type == KJson_String)
            if (!this->data.vstring)
            {
                delete this->data.vstring;
                return;
            }
    
        for (auto iter = mapJ_object.begin(); iter != mapJ_object.end(); iter++)
        {
            if (iter->second != NULL)
                delete iter->second;
        }
        this->mapJ_object.clear();
        for (auto iter = mapJ_array.begin(); iter != mapJ_array.end(); iter++)
        {
            if (iter->second != NULL)
                delete iter->second;
        }
        this->mapJ_array.clear();
    
    }
    
    
    
    
    
    KJson::~KJson()
    {
        Clear();
    }
    KJson& KJson::operator[](const std::string key)    //获得键名为key的键值对
    {
        if(this->type==KJson_Object){
            auto iter = mapJ_object.find(key);
            if (iter == mapJ_object.end())  //找不到
            {
                KJson* jjnew = new KJson();
                jjnew->key = key;
                this->mapJ_object.insert(std::pair<std::string, KJson*>(key, jjnew));
                return (*jjnew);
    
            }
            else
            {
                return (*(iter->second));
            }
        }
        else{
            std::cout << "非对象引用,将返回原值" << std::endl;
            return (*this);
        }
    }
    KJson& KJson::operator[](unsigned int i)
    {
        if (this->type == KJson_Array) {
            auto iter = mapJ_array.find(i);
            if (iter == mapJ_array.end())
            {
    
    
                KJson* jjnew = new KJson();
                this->mapJ_array.insert(std::pair<unsigned int, KJson*>(i, jjnew));
                return (*jjnew);
    
            }
            else return (*(iter->second));
        }
        else 
        {
            std::cout << "非列表引用,将返回原值" << std::endl;
            return (*this);
        }
    }
    std::string KJson::operator()(const std::string key)   
    {
        auto iter = mapJ_object.find(key);
        if (iter == mapJ_object.end())return "我不道啊";
        KJson* jj = iter->second;
        if (jj == NULL) return ("");
        if (jj->type == KJson_String)return *(jj->data.vstring);
        if (jj->type == KJson_Int)
        {
            std::string temp;
            if (jj->sign == NEG)
            {
                if (*(jj->data.vint) <= (long long)INT_MAX && (long long)*(jj->data.vint) >= (long long)INT_MIN)
                {
                    temp = std::to_string((int)*(jj->data.vint));
                }
                else
                {
                    temp = std::to_string((long long int)*(jj->data.vint));
                }
            }
            else
            {
                if ((unsigned long long) * (jj->data.vint) <= (long long)UINT_MAX)
                {
                    temp = std::to_string((unsigned int)*(jj->data.vint));
                }
                else temp = std::to_string((unsigned long long int) * (jj->data.vint));
            }
            return temp;
        }
        if (jj->type == KJson_Double)
        {
            char temp[200] = { 0 };
            if (fabs(*(jj->data.vdouble)) < 0.000001 || fabs(*(jj->data.vdouble)) > 1000000000)
            {
                //to_string方法好像没有转换指数形式的重载,所以用snprintf
                if (jj->sign == NEG)snprintf(temp, sizeof(temp), "-%e", *(jj->data.vdouble));
                else snprintf(temp, sizeof(temp), "%e", *(jj->data.vdouble));
            }
            else
            {
                if (jj->sign == NEG)snprintf(temp, sizeof(temp), "-%f", *(jj->data.vdouble));
                else snprintf(temp, sizeof(temp), "%f", *(jj->data.vdouble));
            }
            return (std::string(temp));
        }
        else if (jj->type == KJson_Bool)
        {
            if (*(jj->data.vbool) == false)return "false";
            else return "true";
        }
        if (jj->type == KJson_Object)
        {
            std::string temp;
            for (auto iter = jj->mapJ_object.begin(); iter != jj->mapJ_object.end(); iter++)
            {
                temp += iter->second->key;
                temp += "   ";
            }
            return temp;
        }
        if (jj->type == KJson_Array)
        {
            std::string temp;
            for (auto iter = jj->mapJ_array.begin(); iter != jj->mapJ_array.end(); iter++)
            {
                temp += iter->second->key;
                temp += "   ";
            }
            return temp;
        }
        return "";
    }
    std::string KJson::operator()(unsigned int i)
    {
        auto iter = mapJ_array.find(i);
        if (iter == mapJ_array.end())return "我不道啊";
        KJson* jj = iter->second;
        if (jj == NULL)return "";
        if (jj->type == KJson_String)return *(jj->data.vstring);
        if (jj->type == KJson_Int)
        {
            std::string temp;
            if (jj->sign == NEG)
            {
                if (*(jj->data.vint) <= (long long)INT_MAX && (long long)*(jj->data.vint) >= (long long)INT_MIN)
                {
                    temp=std::to_string(*(jj->data.vint));
                }
                else temp=std::to_string((long long)*(jj->data.vint));
            }
            else {
                if ((unsigned long long)*(jj->data.vint) <= (unsigned long long)UINT_MAX)
                {
                    temp = std::to_string((unsigned)*(jj->data.vint));
                }
                else temp = std::to_string((unsigned long long)*(jj->data.vint));
            }
            return temp;
        }
        if (jj->type == KJson_Double)
        {
            char temp[200] = { 0 };
            if (fabs(*(jj->data.vdouble))<0.000001||fabs(*(jj->data.vdouble))>100000000)
            {
                if (jj->sign == NEG)
                    snprintf(temp, sizeof(temp), "-%e", *(jj->data.vdouble));
                else
                    snprintf(temp, sizeof(temp), "%e", *(jj->data.vdouble));
            }
            else
            {
                if (jj->sign == NEG)snprintf(temp, sizeof(temp), "-%f", *(jj->data.vdouble));
                else snprintf(temp, sizeof(temp), "%f", *(jj->data.vdouble));
            }
            return (std::string(temp));
        }
        if (jj->type == KJson_Bool)
        {
            if (*(jj->data.vbool) == false)return "false";
            else return "true";
        }
        if (jj->type == KJson_Object)
        {
            std::string temp;
            for (auto iter = jj->mapJ_object.begin(); iter != jj->mapJ_object.end(); iter++)
            {
                temp += iter->second->key;
                temp += "   ";
            }
            return temp;
        }
        if (jj->type == KJson_Array)
        {
            std::string temp;
            for (auto iter = jj->mapJ_array.begin(); iter != jj->mapJ_array.end(); iter++)
            {
                temp += iter->second->key;
                temp += "   ";
            }
            return temp;
        }
        return "";
    }
    std::string KJson::to_string()
    {
        if (this == NULL)return "";
        if (this->type == KJson_String)return "\""+this->key + "\"" + ":" + "\"" + *(this->data.vstring)+"\"" ;
        if (this->type == KJson_Int)
        {
            int num = *(this->data.vint);
            std::string temp;
            if (this->sign == NEG)
            {
                if (num <= (long long)INT_MAX && (long long)num >= (long long)INT_MIN)
                {
                    temp = std::to_string(num);
                }
                else temp = std::to_string((long long)num);
            }
            else {
                if ((unsigned long long) num <= (unsigned long long)UINT_MAX)
                {
                    temp = std::to_string((unsigned)num);
                }
                else temp = std::to_string((unsigned long long) num);
            }
            return "\"" + this->key + "\"" + ":" + temp ;
        }
        if (this->type == KJson_Double)
        {
            char temp[200] = { 0 };
            double num = *(this->data.vdouble);
            if (fabs(num) < 0.000001 || fabs(num) > 100000000)
            {
                if (this->sign == NEG)
                    snprintf(temp, sizeof(temp), "-%e", num);
                else
                    snprintf(temp, sizeof(temp), "%e", num);
            }
            else
            {
                if (this->sign == NEG)snprintf(temp, sizeof(temp), "-%f", num);
                else snprintf(temp, sizeof(temp), "%f", num);
            }
            return "\"" + this->key + "\"" + ":" + std::string(temp);
        }
        if (this->type == KJson_Bool)
        {
            if (*(this->data.vbool) == false)return "\"" +this->key + "\"" + ":" + "\"" + "false" + "\"" ;
            else return "\"" + this->key + "\"" + ":" + "\"" + "true" + "\"" ;
        }
        if (this->type == KJson_Object)
        {
            std::string temp = "";
            if (this->key != "")temp = "\"" + this->key + "\"" +":" + "{";   //对象有名字
            else temp="{";
            if (mapJ_object.begin() == mapJ_object.end())temp += "}";
            else
            {
                temp += "\n";
                for (auto iter = mapJ_object.begin(); iter != mapJ_object.end(); iter++)
                {
                    temp += "   "+(*(iter->second)).to_string() + ",\n";
                }
                temp.erase(temp.size()-2 , 2);
                temp += "\n   }";
            }
            return temp;
        }
        if (this->type == KJson_Array)
        {
            std::string temp = "\"" + this->key+ "\"" +":" + "[";
            if (mapJ_array.begin() == mapJ_array.end())temp += "]";
            else{
                temp += "\n";
                for (auto iter = mapJ_array.begin(); iter != mapJ_array.end(); iter++)
                {
                    temp += "   " + (*(iter->second)).to_string() + ",\n";
                }
                temp.erase(temp.size() - 2, 2);
                temp +="\n   ]";
            }
            return temp;
        }
        return "\"" + this->key + "\"" + ":" + "";
    }
    KJson& KJson::operator=(KJson& jj)
    {
        std::string temp = jj.to_string();
        Clear();
        if (temp[0] != '{') {
            const char* json = temp.c_str();
            json = IgnoreSpace(this->analys_string(IgnoreSpace(json), &error_loc));//处理对象里第一个键值对的键名
            this->key = *(this->data.vstring);
            delete this->data.vstring;
            this->data.vstring = NULL;
            if (*json != ':')
            {
                error_loc = json;
            }
            analys(IgnoreSpace(json + 1), &error_loc);
        }
        else analys(temp.c_str(),&error_loc);
        //为什么要多加一个temp,是因为jj可能是this的孩子,this先Clear了,孩子没了,就转化不了strign了
        return (*this);
    }
    KJson& KJson::operator=(KJson&& jj)
    {
        std::string temp = jj.to_string();
        Clear();
        if (temp[0] != '{') {
            const char* json = temp.c_str();
            json = IgnoreSpace(this->analys_string(IgnoreSpace(json), &error_loc));//处理对象里第一个键值对的键名
            this->key = *(this->data.vstring);
            delete this->data.vstring;
            this->data.vstring = NULL;
            if (*json != ':')
            {
                error_loc = json;
            }
            analys(IgnoreSpace(json + 1), &error_loc);
        }
        else analys(temp.c_str(), &error_loc);
        return (*this);
    }
    KJson& KJson::operator=(std::string vstring)    //对动态键值对进行赋值
    {
        Clear();
        this->type = KJson_String;
        this->data.vstring = new std::string(vstring);
        return *(this);
    }
    KJson& KJson::operator=(int vint)    //对动态键值对进行赋值
    {
        Clear();
        this->type = KJson_Int;
        this->data.vint = new int(vint);
        return *(this);
    }
    KJson& KJson::operator=(double vdouble)    //对动态键值对进行赋值
    {
        Clear();
        this->type = KJson_Double;
        this->data.vdouble = new double(vdouble);
        return *(this);
    }
    int KJson::get_size()
    {
        if (this->type == KJson_Object)return mapJ_object.size();
        if (this->type == KJson_Array)return mapJ_array.size();
        else return -1;
    }
    int KJson::get_type()
    {
        return this->type;
    }

    main.cpp
  • #include"KJson.hpp"
    #include<fstream>
    #include <sstream>
    std::string load(std::string filename = "input.txt");
    bool output(std::string str, std::string filename = "output.txt");
    void chooser(); //交互功能函数
    int main()
    {
        
        chooser();
        //std::string json=                 //解析报错功能测试
        //"{\"refresh_interval\":60,"     
        //                    "\"dynamic_loading\":["
        //                        "{"
        //                            "\"so_path\":\"plugins/User.so\", \"load\":false, \"version\":1,"
        //                            "\"cmd\":["
        //                                 "{\"cmd\":2001, \"class\":\"neb::CmdUserLogin\"},"
        //                                 "{\"cmd\":2003, \"class\":\"neb::CmdUserLogout\"}"
        //                            "],"
        //                            "\"module\":["
        //                                 "{\"path\":\"im/user/login\", \"class\":\"neb::ModuleLogin\"},"
        //                                 "{\"path\":\"im/user/logout\", \"class\":\"neb::ModuleLogout\"}"
        //                            "]"
        //                         "},"
        //    "wrongmessage"                  //错误信息
        //                         "{"
        //                         "\"so_path\":\"plugins/ChatMsg.so\", \"load\":false, \"version\":1,"
        //                             "\"cmd\":["
        //                                  "{\"cmd\":2001, \"class\":\"neb::CmdChat\"}"
        //                             "],"
        //                         "\"module\":[]"
        //                         "}"
        //                    "]"
        //    "}";
        //KJson jj(json);
        //std::string json1 = load("res/json_error.txt");
        //KJson jj1(json1);
    
    
    
    
        /*std::string json="{\"dynamic\":60"        //动态键值对测试
            "}";
        std::string json2 = load();
        KJson jj;
        KJson jj2;
        jj2= KJson(json2);
        jj=KJson (json);
        std::cout << (jj).to_string();
        jj.tests = "jj";
        KJson jj1;
        jj1 = jj;
        jj["data"] = 30;
        jj["new"] = jj2;
        std::cout << jj.to_string();*/
        return 0;
    }
    std::string load(std::string filename)
    {
        std::ifstream file(filename); // 以二进制模式打开文件
        std::stringstream buffer;
        if (!file.is_open()) {
            printf("文件打开异常!\n");//文件打开异常
            return "";
        }
        buffer << file.rdbuf();
        file.close();
        return buffer.str();
    }
    bool output(std::string str, std::string filename)
    {
        std::ofstream file(filename);
        if (!file.is_open()) {
            printf("文件写入异常!");
            return false;
        }
        file << str;
        return true;
    }
    void chooser()
    {
        int choice;
        int choice1 = 1;
        int choice2 = 1;
        std::string filename;
        std::string json = load();
        std::string key;
        std::string info;
        KJson jj(json);
        KJson jjnew;
        while (true) {
            std::cout << "--------------------------------------------------\n"
                "输入:0结束,1选择json文件(可缺省),2查询,3输出为json文件"<<std::endl;
            if (!scanf_s("%d", &choice))
            {
                std::cout << "输入错误!";
                int c;
                while ((c = getchar()) != '\n' && c != EOF);
            }
            else if (!choice)return;
            else if (choice == 1)    //不选择文件就缺省打开作业给的文件
            {
                std::string temp;
                std::cout << "请输入文件名";
                std::cin >> filename;
                temp =load(filename);
                if (temp != "")json = temp;
            }
            else if (choice == 2)
            {
                jj = KJson(json);
                jjnew = jj;
                int i;
                switch (jjnew.get_type())
                {
                case KJson_Bool:std::cout << "这是一个布尔类型" << std::endl; break;
                case KJson_Int:std::cout << "这是一个整形类型" << std::endl; break;
                case KJson_Double:std::cout << "这是一个浮点类型" << std::endl; break;
                case KJson_NULL:std::cout << "这是一个空值" << std::endl; break;
                case KJson_String:std::cout << "这是一个字符串类型" << std::endl; break;
                case KJson_Object:
                    std::cout << "这是一个对象 "<<std::endl ;
                    break;
                default:std::cout << "到顶"; break;
                }
                while (true)
                {
                    std::cout << "--------------------------------------------------\n"
                        "0结束查询,1进行查询,2回退到初始";
                    if (!scanf_s("%d", &choice1))
                    {
                        std::cout << "输入错误!";
                        int c;
                        while ((c = getchar()) != '\n' && c != EOF);
                        break;
                    }
                    if (!choice1)
                        break;
                    if (choice1 == 1)
                    {
                        std::cout << "请输入要访问的键名或下标" << std::endl;
                        if (jjnew.get_type() != KJson_Array)
                        {
                            std::cin >> key;
                            info = jjnew(key);
                            if (info == "")
                            {
                                std::cout << "查无此项,是否进行添加?\n"
                                    "0不添加,1添加" << std::endl;
                                std::cin >> choice2;
                                if (choice2)
                                {
                                    std::cout << "输入值:";
                                    std::cin >> info;
                                    jjnew[key] = info;
                                }
                            }
                            else
                            {
                                jjnew = jjnew[key];
                                switch (jjnew.get_type())
                                {
                                case KJson_Bool:std::cout << "这是一个布尔类型,值为" + info << std::endl; break;
                                case KJson_Int:std::cout << "这是一个整形类型,值为" + info << std::endl; break;
                                case KJson_Double:std::cout << "这是一个浮点类型,值为" + info << std::endl; break;
                                case KJson_NULL:std::cout << "这是一个空值" << std::endl; break;
                                case KJson_String:std::cout << "这是一个字符串类型,值为" + info << std::endl; break;
                                case KJson_Object:
                                    std::cout << "这是一个对象,键值对个数: " << jjnew.get_size() << std::endl;
                                    std::cout << "键值对的键名如下:" + info << std::endl;
                                    break;
                                case KJson_Array:
                                    std::cout << "这是一个列表,键值对个数: " << jjnew.get_size()<<std::endl;
                                    break;
                                default:std::cout << "该项未初始化"; break;
                                }
                            }
                        }
                        else
                        {
                            std::cin >> i;
                            info = jjnew(i);
                            if (info == "")
                            {
                                std::cout << "下标超出范围,是否进行添加一个新元素进列表?\n"
                                    "0不添加,1添加" << std::endl;
                                std::cin >> choice2;
                                if (choice2)
                                {
                                    std::cout << "输入值:";
                                    std::cin >> info;
                                    jjnew[jjnew.get_size()] = info;
                                }
                            }
                            else
                            {
                                jjnew = jjnew[i];
                                switch (jjnew.get_type())
                                {
                                case KJson_Bool:std::cout << "这是一个布尔类型" << std::endl; break;
                                case KJson_Int:std::cout << "这是一个整形类型" << std::endl; break;
                                case KJson_Double:std::cout << "这是一个浮点类型" << std::endl; break;
                                case KJson_NULL:std::cout << "这是一个空值" << std::endl; break;
                                case KJson_String:std::cout << "这是一个字符串类型" << std::endl; break;
                                case KJson_Object:
                                    std::cout << "这是一个对象,键值对个数: " << jjnew.get_size()<<std::endl;
                                    std::cout << "键值对的键名如下:" + info << std::endl;
                                    break;
                                case KJson_Array:
                                    std::cout << "这是一个列表,键值对个数: " << jjnew.get_size()<<std::endl;
                                    break;
                                default:std::cout << "该项未初始化" << std::endl; break;
                                }
                            }
                        }
                    }
                    else if (choice1 == 2)
                    {
    
                        jjnew = jj;
                    }
                    else 
                    {
                        std::cout << "输入错误!";
                        break;
                    }
                }
            }
            else if (choice == 3)
            {
                if (jj.get_type() != NOT_INITIAL)
                {
                    std::cout << "输入要目标文件名:" << std::endl;
                    std::cin >> filename;
                    output((jj).to_string(), filename);
                }
                else std::cout << "目前还未读取json!" << std::endl;
            }
        }
    }
    

    对于输入文件input.txt,下面给出一个示例:

{
    "time": "2018-09-22 12:37:21",
    "cityInfo": {
        "city": "天津市", 
        "cityId": "101030100",
        "parent": "天津",
        "updateTime": "12:32"
    },
    "date": "20180922",
    "message": "Success !",
    "status": 200,
    "data": {
        "shidu": "22%",
        "pm25": 15.0,
        "pm10": 46.0,
        "quality": "优",
        "wendu": "24",
        "ganmao": "各类人群可自由活动",
        "yesterday": {
            "date": "21",
            "ymd": "2018-09-21",
            "week": "星期五",
            "sunrise": "05:56",
            "high": "高温 25.0℃",
            "low": "低温 15.0℃",
            "sunset": "18:12",
            "aqi": 108.0,
            "fx": "西北风",
            "fl": "4-5级",
            "type": "晴",
            "notice": "愿你拥有比阳光明媚的心情"
        },
        "forecast": [
            {
                "date": "22",
                "ymd": "2018-09-22",
                "week": "星期六",
                "sunrise": "05:57",
                "high": "高温 26.0℃",
                "low": "低温 15.0℃",
                "sunset": "18:10",
                "aqi": 55.0,
                "fx": "西北风",
                "fl": "4-5级",
                "type": "晴",
                "notice": "愿你拥有比阳光明媚的心情"
            },
            {
                "date": "23",
                "ymd": "2018-09-22",
                "week": "星期日",
                "sunrise": "05:58",
                "high": "高温 23.0℃",
                "low": "低温 14.0℃",
                "sunset": "18:09",
                "aqi": 29.0,
                "fx": "西北风",
                "fl": "4-5级",
                "type": "晴",
                "notice": "愿你拥有比阳光明媚的心情"
            },
            {
                "date": "24",
                "ymd": "2018-09-22",
                "week": "星期一",
                "sunrise": "05:59",
                "high": "高温 24.0℃",
                "low": "低温 15.0℃",
                "sunset": "18:07",
                "aqi": 25.0,
                "fx": "西北风",
                "fl": "<3级",
                "type": "晴",
                "notice": "愿你拥有比阳光明媚的心情"
            },
            {
                "date": "25",
                "ymd": "2018-09-22",
                "week": "星期二",
                "sunrise": "06:00",
                "high": "高温 24.0℃",
                "low": "低温 16.0℃",
                "sunset": "18:05",
                "aqi": 56.0,
                "fx": "西南风",
                "fl": "<3级",
                "type": "晴",
                "notice": "愿你拥有比阳光明媚的心情"
            },
            {
                "date": "26",
                "ymd": "2018-09-22",
                "week": "星期三",
                "sunrise": "06:01",
                "high": "高温 24.0℃",
                "low": "低温 17.0℃",
                "sunset": "18:04",
                "aqi": 86.0,
                "fx": "西南风",
                "fl": "3-4级",
                "type": "阴",
                "notice": "不要被阴云遮挡住好心情"
            }
        ]
    }
}

交互界面的使用示例如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值