最近在青海,背单词/写代码/练琴…并不是旅游…心酸。
网络信号不好,也长期处在外,所以博客有一段时间没有更新了。
这一次我们就写一个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{
};
这一节打个基础,下一节说词法分析。