Json解析器全独立cpp版本实现(一)

Aug 7, 2017


最近在青海,背单词/写代码/练琴…并不是旅游…心酸。

网络信号不好,也长期处在外,所以博客有一段时间没有更新了。

这一次我们就写一个Json解析器吧,当然我们知道用弱类型语言写Json解析器很简单,但我们自然要挑战一些难度什么的。

这一次我们用C艹来写一个Json的解析器。

面向:会Json语法并且会编译原理基本内容的同学,就不多说Json的语法规则和解析步骤了。

六种基本类型

玩过Json的同学自然知道Json的六种基本类型:

  • Number
  • Bool
  • String
  • Array
  • Object
  • Null

比如下面一段Json文本;

{
     "data": 100,
     "datas": [100, 200, 300, 400],
     "allDatas":{
         "data1": 100,
         "data2": true,
         "data3": null,
         "data4": "dddd"
     }
}

Number自然是指普通的数字,整数或者浮点。

Bool自然是指true还是false。

String自然是指字符串,比如“ssss”。

Array自然是指一系列的用中括号[]括起来的元素的顺序集合,比如[“sss”, 34, 34.5, true, null]。

Object指Json的一个大括号括起来的一系列键值对, 比如{“1”: “ss”, “2”: “sss”},当然Object可以嵌套,一个Json对象其实就是一个Object。

Null自然就是空。

其他的不多说了,不熟练的同学可以去搜一搜百科,或者看看其他的文档什么,这里主要讲解析器的实现。

六种基本类型实现的原理

我们知道,Cpp是强类型语言,而Json的六种基本类型是那么的坑爹,如果我要写解析器,对于Json的键值对的形式来讲,自然是要写一个解析值的函数比如parseValue(),那么一般的人在JS语言中会这么写。

function parseValue(){
	if(xxx){
		return parseNumber()
	}else if(xxx){
		return parseBool()
	}else if(xxx){
		return parseString()
	}else if(xxx){
		return parseArray()
	}else if(xxx){
		return parseObject()
	}else{
		return parseNull()
	}
}

这样就可以直接得到解析出来冒号后面的那个值了,不过我们的第一道门槛就是Cpp是强类型语言,无法弱类型返回。自然我们要使用Cpp中的多态的特性来满足这一要求,所以我们先定义下面几个类,其中JsonValue可以看成是一个抽象类。

class JsonValue{};

class JsonNumber: JsonValue{};
class JsonBool  : JsonValue{};
class JsonString: JsonValue{};
class JsonArray : JsonValue{};
class JsonObject: JsonValue{};
class JsonNull  : JsonValue{};

这样就可以假装定义好了六种基本类型,当调用JsonValue类型的指针的时候,这个指针就可以变成六种类型之一了,相当于实现了我们上面所说的需求—–假装拥有弱类型。

六种类型的实现

只讲头文件内容,具体函数实现在我的Github里。

首先来个枚举类型,说明各个对象的类型:

enum JSONTYPE{
    JSON_NUMBER,
    JSON_BOOL,
    JSON_STRING,
    JSON_ARRAY,
    JSON_OBJECT,
    JSON_NULL
};

然后就是JsonValue这个爸爸类,其中union是数据域,也就是如果是bool或者number的时候保存数据的位置。

然后getString这个虚函数是所有的类型都要带的,是将Json对象转换成Json字符串的形式,因为我们还有一个stringify的函数要写,用这个很方便。

是实现多态的基础:

class JsonValue{
protected:
    JSONTYPE type;
    union{
        bool valueBool;
        double valueNumber;
        std::string valueString;
    };
public:
    JsonValue(){}
    ~JsonValue(){}
    virtual std::string getString(){}
    JSONTYPE getType(){ return type; }
};

JsonNumber,很简单,不多说:

class JsonNumber: public JsonValue{
public:
    JsonNumber();
    JsonNumber(double num);
    std::string getString();
    double getNumber();
};

JsonBool,很简单,不多说:

class JsonBool: public JsonValue{
public:
    JsonBool();
    JsonBool(bool value);
    std::string getString();
    bool getBool();
};

JsonString,很简单,不多说:

class JsonString: public JsonValue{
public:
    JsonString();
    JsonString(std::string value);
    std::string getString();
};

JsonArray,这里所有的容器里都必须是JsonValue指针,只有JsonValue指针能够实现多态变成上述的六种类型。主体是vector<JsonValue*>:

class JsonArray: public JsonValue{
private:
    std::vector<JsonValue*> array;
public:
    JsonArray();
    JsonArray(std::vector<JsonValue*> value);
    std::string getString();
    std::vector<JsonValue*> getArray();
    void append(JsonValue* value);
    JsonValue* pop();
};

JsonObject,同上,这里的主体是map<JsonValue, JsonValue>:

class JsonObject: public JsonValue{
private:
    std::map<JsonValue*, JsonValue*> object;
public:
    JsonObject();
    JsonObject(std::map<JsonValue*, JsonValue*> value);
    JsonObject(JsonValue* first, JsonValue* second);
    std::string getString();
    std::map<JsonValue*, JsonValue*> getObject();
    void append(JsonValue* first, JsonValue* second);
    JsonValue* getValue(JsonValue* key);
};

class JsonTokenizer{

};

这一节打个基础,下一节说词法分析。