json解析器的代码实现

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

基本功能:

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

进阶功能

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

待完善功能:

  • XML序列化格式支持: 扩展序列化功能,使其支持JSON序列化转为XML序列化
  • 多线程安全:确保对多线程环境中对JSON对象访问和修改不会产生竞争条件。

KJson.hpp

点击查看代码
#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回退到初始"<<std::endl;
                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 << "查无此项,是否进行添加?" << std::endl<<
                                "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

对于输入文件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": "不要被阴云遮挡住好心情"
            }
        ]
    }
}

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

posted @ 2025-02-20 14:57  Travic  阅读(58)  评论(0)    收藏  举报