目录
Ⅰ:格式解析篇
一:JSON格式解析初步
我们都知道JSON格式是怎么样的,在这里我们不详细说明JSON的格式,如果需要查看更详细的介绍,可以去JSON中国网站查询。在这里,我们只介绍JSON格式的解析过程。
那么,要解析JSON格式,我们到底需要怎么做呢?本文主要分两步:
- 找有效字符:抽出JSON字符串中的有效字符,我们叫它Token,并且如果符合条件的话,就将它们一个个入队。
- 组合JsonValue对象:每次出队一个有效字符Token,通过有效字符的类型[对象/数组/单值],递归组合JsonValue对象。
二:Token解析
根据上述的步骤,首先我们需要找出Json字符串中的Token。那么token都有哪些?主要有如下几个:
token名称 | 描述 |
---|---|
ObjectBegin | 对象开始 |
ObjectEnd | 对象结束 |
ArrayBegin | 数组开始 |
ArrayEnd | 数组结束 |
ObjectKeyValueSeparator | 对象键值对的分割符,也就是’:’ |
MemberSeparator | 成员分割符,也就是’,’ |
String | 字符串 |
Double | 实数 |
LongLong | 整型 |
True | true值 |
False | false值 |
Null | 空值 |
为了解析出Token,我们需要一种方法:有限状态自动机,这种方法用来解析协议非常有效,前边我们用它解析了HTTP协议,本次我们同样可以用它来解析出JSON字符串中的token。感兴趣的可以参考文章C++使用有限状态自动机编程解析HTTP协议
我们需要找出状态机中Token解析的所有状态,如下表所示:
Token解析状态 | 状态描述 |
---|---|
BEGIN | 开始解析,是各种可以作为开始字符的Token |
OBJECT_OR_ARRAY_BEGIN | 数组或者对象的开始,’{’ 或者 ‘]’ 字符 |
STRING_BEGIN | 字符串开始,也就是 ‘"’ 字符 |
STRING | 解析字符串过程中 |
NUMBER_BEGIN | 数字开始,遇到’0’ - ‘9’ 或者 ‘-’ 的时候,就是要开始解析数子了 |
NUMBER_POINT | 小数点,解析到小数点的时候 |
NUMBER_BEFORE_POINT | 解析小数点前的数字 |
END | 结束的状态,也就是 ‘}’ 或者 ‘]’ 或者 ‘:’ 或者 ‘,’ 或者空格等等,都可以作为一个Token的结束状态 |
N_IN_NULL | null中的n |
NU_IN_NULL | null中的nu |
NUL_IN_NULL | null中的nul |
T_IN_TRUE | true中的t |
TR_IN_TRUE | true中的tr |
TRU_IN_TRUE | true中的tru |
F_IN_FALSE | false中的f |
FA_IN_FALSE | false中的fa |
FAL_IN_FALSE | false中的fal |
FALS_IN_FALSE | false中的fals |
ESCAPE | 遇到字符串中的 ‘’ 的时候,可能是需要转义的时候 |
ERROR | 错误的状态 |
有了上述的这些解析状态和Token,我们就可以编码开始解析出字符串中的Token了[状态机就不画了,看代码更加清楚细节]。
//json是std::vector<char>类型的字符串
std::vector<char>::const_iterator p = json.begin();//当前的指针
ParserState state = ParserState::BEGIN;
std::list<JsonToken> tokens;//存放有效的token
//状态机自我运行中
while (state != ParserState::ERROR && p != json.end()) {
char ch = *p;
auto cur = p++;
switch (state) {
case ParserState::BEGIN: {
if (isSpace(ch)) {
//do nothing
} else if (isBeginOfValue(ch)) {
//判断是不是开始符号或者结束符号,那么就添加上去,同时状态还是这个开始状态,因为等着解析其他的字符
pushBackIfToken(tokens, ch, cur);
state = ParserState::OBJECT_OR_ARRAY_BEGIN;
} else if (ch == '"') {
//字符串
state = ParserState::STRING_BEGIN;
} else if (ch >= '0' && ch <= '9') {
tokens.emplace_back(TokenType::Double, cur);
p--;//记住,指针要向前移动
state = ParserState::NUMBER_BEGIN;
} else if (ch == '-') {
//解析负数指针不用向前移动
tokens.emplace_back(TokenType::Double, cur);
state = ParserState::NUMBER_BEGIN;
} else if (ch == 'f') {
//解析false
tokens.emplace_back(TokenType::False, cur);
state = ParserState::F_IN_FALSE;
} else if (ch == 't') {
tokens.emplace_back(TokenType::True, cur);
state = ParserState::T_IN_TRUE;
} else if (ch == 'n') {
tokens.emplace_back(TokenType::Null, cur);
state = ParserState::N_IN_NULL;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::OBJECT_OR_ARRAY_BEGIN: {
if (isSpace(ch)) {
//do nothing
} else if (isEndOfValue(ch)) {
//如果是结束符,那么下一个状态为值结束状态
pushBackIfToken(tokens, ch, cur);
state = ParserState::END;
} else {
p--;//注意要退一格
state = ParserState::BEGIN;
}
break;
}
case ParserState::N_IN_NULL: {
state = ch == 'u' ? ParserState::NU_IN_NULL : ParserState::ERROR;
break;
}
case ParserState::NU_IN_NULL: {
state = ch == 'l' ? ParserState::NUL_IN_NULL : ParserState::ERROR;
break;
}
case ParserState::NUL_IN_NULL: {
if (ch == 'l') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::T_IN_TRUE: {
state = ch == 'r' ? ParserState::TR_IN_TRUE : ParserState::ERROR;
break;
}
case ParserState::TR_IN_TRUE: {
state = ch == 'u' ? ParserState::TRU_IN_TRUE : ParserState::ERROR;
break;
}
case ParserState::TRU_IN_TRUE: {
if (ch == 'e') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::F_IN_FALSE: {
state = ch == 'a' ? ParserState::FA_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FA_IN_FALSE: {
state = ch == 'l' ? ParserState::FAL_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FAL_IN_FALSE: {
state = ch == 's' ? ParserState::FALS_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FALS_IN_FALSE: {
if (ch == 'e') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::ESCAPE: {
//遇到转义的,回到前一个状态
state = ParserState::STRING;//转义是在字符串才有的,所以回到字符串状态
break;
}
case ParserState::STRING_BEGIN: {
tokens.emplace_back(TokenType::String, cur);//栈顶元素为字符串类型
//解析字符串
state = ParserState::STRING;
break;
}
case ParserState::STRING: {
//字符串
if (ch == '"') {
//字符串结束
//取出栈顶的元素,记录位置
tokens.back().end = cur;
state = ParserState::END;
} else if (ch == '\\') {
//转义的话
state = ParserState::ESCAPE;
}
break;
}
case ParserState::END: {
//如果是结尾的符,就一直解析,解析到不是结尾符为止
if (isSpace(ch) || isSeparator(ch) || isEndOfValue(ch)) {
pushBackIfToken(tokens, ch, cur);
} else {
//不是结尾符,那么转到开始状态,注意需要改变当前指针
p--;
state = ParserState::BEGIN;
}
break;
}
case ParserState::NUMBER_BEGIN: {
//解析数字
if (ch == '0') {
//解析0或者小数
state = ParserState::NUMBER_POINT;
} else if (ch >= '1' && ch <= '9') {
state = ParserState::NUMBER_BEFORE_POINT;//小数点之前的数字
} else {
//其他情况都是错误的
state = ParserState::ERROR;
}
break;
}
case ParserState::NUMBER_POINT: {
//遇到0开头的数字
if (ch == '.') {
//解析小数
state = ParserState::NUMBER_AFTER_POINT;//小数点之后的数字
} else if (ch == ',' || isSpace(ch) || isEndOfValue(ch)) {
tokens.back().type = TokenType::LongLong;
tokens.back().end = cur;
p--;//退一格
state = ParserState::END;
} else {
//其他情况都是不允许的
state = ParserState::ERROR;
}
break;
}
case ParserState::NUMBER_BEFORE_POINT: {
//遇到0开头的数字
if (ch >= '0' && ch <= '9') {
//do nothing
} else {
//其他情况根ZERO_NUMBER_POINT一样,不过指针需要向前移动
p--;
state = ParserState::NUMBER_POINT;//小数点之后的数字
}
break;
}
case ParserState::NUMBER_AFTER_POINT: {
//小数点前后,可以是0-9任何数字
if (ch >= '0' && ch <= '9') {
//do nothing
} else if (ch == ',' || isSpace(ch) || isEndOfValue(ch)) {
tokens.back().end = cur;
p--;//退一格
state = ParserState::END;
} else {
//其他情况都是不允许的
state = ParserState::ERROR;
}
break;
}
default:
break;
}
}
三:JsonValue的组装
有了上述解析出来的tokens,我们就可以实行下一步计划----组装JsonValue。由于Json结构天然是一个递归结构,所以不出意外,本文也是主要运用递归算法来组装。递归思想的步骤也很简单:
- 出队一个Token
- 遇到ObjectBegin类型,表示需要解析对象了,转步骤5
- 遇到ArrayBegin类型,表示需要解析数组了,就去递归解析数组,直达遇到单值类型
- 遇到单值类型[String,True,False,Double,LongLong,Null]的时候,直接解析出它们的值,存到JsonValue中,结束本次递归。
- 递归循环解析对象中的每一个key和value,依次先出队一个key,再出队一个ObjectKeyValueSeparator[ ‘:’ ],再递归解析出一个value,组装到JsonValue中
- 递归循环解析数组中的每一个item,先递归解析出一个item,再出队一个MemberSeparator[ ‘,’ ],依次组装到JsonValue中。
编码如下:
JsonValue JsonParser::genJsonValueViaTokens(std::list<JsonToken> &tokens) {
//先出队一个元素
JsonToken token = tokens.front();
//当前处理的是值
tokens.pop_front();
if (TokenType::ObjectBegin == token.type) {
//当前处理的是对象
return genJsonObjectViaTokens(tokens);
} else if (TokenType::ArrayBegin == token.type) {
//当前处理的是数组
return genJsonArrayViaTokens(tokens);
}
//下面的情况的值是普通类型的
if (TokenType::String == token.type) {
return JsonValue(token.start, token.end);//当前是字符串
} else if (TokenType::True == token.type) {
return JsonValue(true);//当前是布尔型
} else if (TokenType::False == token.type) {
return JsonValue(false);//当前是布尔型
} else if (TokenType::Double == token.type) {
return JsonValue(std::atof(std::string(token.start, token.end).c_str()));//当前是实数
} else if (TokenType::LongLong == token.type) {
return JsonValue(std::atoll(std::string(token.start, token.end).c_str()));//当前是实数
} else if (TokenType::Null == token.type) {
return JsonValue();
}
return JsonValue();
}
//解析数组
JsonValue JsonParser::genJsonArrayViaTokens(std::list<JsonToken> &tokens) {
JsonArray jsonArray;
//找到第一个']'然后不停出队
while (TokenType::ArrayEnd != tokens.front().type) {
jsonArray.append(genJsonValueViaTokens(tokens));
//如果还没有遇到]结束符队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
//然后去掉数组间的分割符
if (TokenType::MemberSeparator == tokens.front().type) {
tokens.pop_front();//','
} else if (TokenType::ArrayEnd == tokens.front().type) {
//do nothing
} else {
return JsonValue();
}
}
//循环结束后,类型为ArrayBegin,需要pop掉
tokens.pop_front();
return jsonArray;
}
//解析对象
JsonValue JsonParser::genJsonObjectViaTokens(std::list<JsonToken> &tokens) {
JsonObject jsonObject;
//找到第一个'}'然后不停出队
while (TokenType::ObjectEnd != tokens.front().type) {
//再出队key
JsonToken key = tokens.front();
tokens.pop_front();
//然后去掉对象间的分割符':'
if (tokens.front().type != TokenType::ObjectKeyValueSeparator) {
return false;
}
//如果还没有遇到:队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
tokens.pop_front();//':'
//再出队value
jsonObject.insert(std::string(key.start, key.end), genJsonValueViaTokens(tokens));
//如果还没有遇到}队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
//最后再去掉对象值之间的分割符
if (TokenType::MemberSeparator == tokens.front().type) {
tokens.pop_front();//','
} else if (TokenType::ObjectEnd == tokens.front().type) {
//do nothing
} else {
return JsonValue();
}
}
//循环结束后,类型为TokenType::ObjectBegin,需要pop掉
tokens.pop_front();
return jsonObject;
}
四、JSON解析全部代码
jsonvalue.h
#pragma once
#include <map>
#include <vector>
#include <string>
struct JsonObject;
struct JsonArray;
struct JsonValue;
enum class JsonValueType {
Null = 0,
LongLong,//整型[64位的]
Double,//实数
String,
Boolean,
Array,
Object
};
/**
* json对象
*/
struct JsonObject {
void insert(const std::string &key, const JsonValue &value);
bool contains(const std::string &key) const;
const JsonValue &operator[](const std::string &key) const;
std::map<std::string, JsonValue>::const_iterator begin() const;
std::map<std::string, JsonValue>::const_iterator end() const;
private:
std::map<std::string, JsonValue> _object;//对象
};
/**
* json数组
*/
struct JsonArray {
void append(const JsonValue &value);
const JsonValue &operator[](size_t index) const;
std::vector<JsonValue>::const_iterator begin() const;
std::vector<JsonValue>::const_iterator end() const;
private:
std::vector<JsonValue> _array;//数组
};
/**
* Json的值对象
*/
struct JsonValue {
JsonValue();
JsonValue(const std::string &value);
JsonValue(const char *value);
JsonValue(const std::vector<char>::const_iterator &begin, const std::vector<char>::const_iterator &end);
JsonValue(long long value);
JsonValue(int value);
JsonValue(bool value);
JsonValue(double value);
JsonValue(const std::vector<char> &value);
JsonValue(const JsonObject &value);
JsonValue(const JsonArray &value);
JsonValueType type() const;
double toDouble() const;
long long toLongLong() const;
std::string toString() const;
bool toBoolean() const;
JsonArray toArray() const;
JsonObject toObject() const;
//赋值
JsonValue(const JsonValue &other);
JsonValue &operator=(const JsonValue &other);
~JsonValue();
private:
/**
* 交换指针内容
* @param other
*/
void swap(JsonValue &other);
void setType(JsonValueType type);
JsonValueType _type;
//保存值
union {
double _real;
long long _number;
bool _bool;
std::string *_string;//字符串
JsonObject *_object;//对象
JsonArray *_array;//数组
} _value;
};
jsonvalue.cpp
#include "jsonvalue.h"
#include <algorithm>
JsonValue::JsonValue() {
setType(JsonValueType::Null);
}
JsonValue::JsonValue(const std::string &str) {
setType(JsonValueType::String);
_value._string->assign(str);
}
JsonValue::JsonValue(const char *value) : JsonValue(std::string(value)) {}
JsonValue::JsonValue(const JsonArray &value) {
setType(JsonValueType::Array);
*_value._array = value;
}
JsonValue::JsonValue(bool value) {
setType(JsonValueType::Boolean);
_value._bool = value;
}
JsonValue::JsonValue(long long value) {
setType(JsonValueType::LongLong);
_value._number = value;
}
JsonValue::JsonValue(double value) {
setType(JsonValueType::Double);
_value._real = value;
}
JsonValue::JsonValue(const std::vector<char> &value) : JsonValue(value.begin(), value.end()) {}
JsonValue::JsonValue(const JsonObject &value) {
setType(JsonValueType::Object);
*_value._object = value;
}
JsonValue::JsonValue(int value) : JsonValue((long long) value) {}
JsonValue::JsonValue(const std::vector<char>::const_iterator &begin, const std::vector<char>::const_iterator &end) {
setType(JsonValueType::String);
_value._string->assign(begin, end);
}
double JsonValue::toDouble() const {
if (JsonValueType::Double == _type) {
return _value._real;
}
return 0.0;
}
long long JsonValue::toLongLong() const {
if (JsonValueType::LongLong == _type) {
return _value._number;
}
return 0;
}
std::string JsonValue::toString() const {
if (JsonValueType::String == _type) {
return std::string(_value._string->begin(), _value._string->end());
}
return std::string();
}
JsonValueType JsonValue::type() const {
return _type;
}
bool JsonValue::toBoolean() const {
if (JsonValueType::Boolean == _type) {
return _value._bool;
}
return false;
}
JsonArray JsonValue::toArray() const {
if (JsonValueType::Array == _type) {
return *_value._array;
}
return JsonArray();
}
JsonObject JsonValue::toObject() const {
if (JsonValueType::Object == _type) {
return *_value._object;
}
return JsonObject();
}
void JsonValue::setType(JsonValueType type) {
//初始化
_type = type;
_value._string = NULL;
static std::string emptyString = "";
switch (_type) {
case JsonValueType::Null:
break;
case JsonValueType::Double:
_value._real = 0.0;
break;
case JsonValueType::LongLong:
_value._real = 0;
break;
case JsonValueType::String:
_value._string = new std::string(emptyString);
break;
case JsonValueType::Array:
_value._array = new JsonArray();
break;
case JsonValueType::Object:
_value._object = new JsonObject();
break;
case JsonValueType::Boolean:
_value._bool = false;
break;
default:
break;
}
}
void JsonObject::insert(const std::string &key, const JsonValue &value) {
_object.emplace(key, value);
}
std::map<std::string, JsonValue>::const_iterator JsonObject::begin() const {
return _object.begin();
}
std::map<std::string, JsonValue>::const_iterator JsonObject::end() const {
return _object.end();
}
bool JsonObject::contains(const std::string &key) const {
return _object.find(key) != _object.end();
}
const JsonValue &JsonObject::operator[](const std::string &key) const {
auto it = _object.find(key);
return (*it).second;
}
void JsonArray::append(const JsonValue &value) {
_array.push_back(value);
}
std::vector<JsonValue>::const_iterator JsonArray::begin() const {
return _array.begin();
}
std::vector<JsonValue>::const_iterator JsonArray::end() const {
return _array.end();
}
const JsonValue &JsonArray::operator[](size_t index) const {
return _array[index];
}
JsonValue::JsonValue(const JsonValue &other) {
//负责other的内容到this中
_type = other.type();
switch (_type) {
case JsonValueType::Null:
case JsonValueType::Double:
case JsonValueType::LongLong:
case JsonValueType::Boolean:
_value = other._value;
break;
case JsonValueType::String:
_value._string = new std::string(*other._value._string);
break;
case JsonValueType::Array:
_value._array = new JsonArray(*other._value._array);
break;
case JsonValueType::Object:
_value._object = new JsonObject(*other._value._object);
break;
default:
break;
}
}
void JsonValue::swap(JsonValue &other) {
//交换类型和值
std::swap(_value, other._value);
std::swap(_type, other._type);
}
JsonValue &JsonValue::operator=(const JsonValue &other) {
JsonValue(other).swap(*this);
return *this;
}
JsonValue::~JsonValue() {
switch (_type) {
case JsonValueType::String:
delete _value._string;
break;
case JsonValueType::Array:
delete _value._array;
break;
case JsonValueType::Object:
delete _value._object;
break;
default:
break;
}
_value._number = 0;
}
jsonparser.h
#pragma once
#include <vector>
#include <list>
#include "jsonvalue.h"
enum class TokenType {
ObjectBegin = 0,//对象开始
ObjectEnd,//对象结束
ArrayBegin,//数组开始
ArrayEnd,//数组结束
ObjectKeyValueSeparator,//对象键值对的分割符,也就是':'
MemberSeparator,//成员分割符,也就是','
String,//字符串
Double,//实数
LongLong,//整型
True,
False,
Null//空值
};
struct JsonToken {
TokenType type;
std::vector<char>::const_iterator start;
std::vector<char>::const_iterator end;
JsonToken(TokenType type, const std::vector<char>::const_iterator &start) : type(type), start(start), end(start) {}
};
struct JsonParser {
/**
* 将json转为JsonValue
* JsonValue: 返回的值
*/
static JsonValue parse(const std::vector<char> &json);
/**
* 将jsonValue转为Json
* json: 返回的值
*/
static std::vector<char> parse(const JsonValue &root);
private:
//跳过空的
static bool isSpace(char ch);
/**
* 判断是不是结束符
* @param ch
* @return
*/
static bool isEndOfValue(char ch);
/**
* 是不是开始符
* @param ch
* @return
*/
static bool isBeginOfValue(char ch);
/**
* 判断是不是分割符
* @param ch
* @return
*/
static bool isSeparator(char ch);
/**
* 如果是token就加入token列表
* @param ch
*/
static void pushBackIfToken(std::list<JsonToken> &tokens, char ch, const std::vector<char>::const_iterator &pos);
//通过token生成jsonValue
static JsonValue genJsonValueViaTokens(std::list<JsonToken> &tokens);
//通过token生成jsonArray
static JsonValue genJsonArrayViaTokens(std::list<JsonToken> &tokens);
//通过token生成jsonObject
static JsonValue genJsonObjectViaTokens(std::list<JsonToken> &tokens);
};
jsonparser.cpp
#include "jsonparser.h"
enum class ParserState {
BEGIN = 0,//开始解析
OBJECT_OR_ARRAY_BEGIN,//如果是数组或者对象
STRING_BEGIN,//字符串开始
STRING,//解析字符串过程中
NUMBER_BEGIN,//数字开始
NUMBER_POINT,//小数点
NUMBER_BEFORE_POINT,//解析小数点前的数字
NUMBER_AFTER_POINT,//解析小数点后的数字
END,//结束的状态
N_IN_NULL,
NU_IN_NULL,
NUL_IN_NULL,
T_IN_TRUE,
TR_IN_TRUE,
TRU_IN_TRUE,
F_IN_FALSE,
FA_IN_FALSE,
FAL_IN_FALSE,
FALS_IN_FALSE,
ESCAPE,//转义/
ERROR//错误的状态
};
JsonValue JsonParser::parse(const std::vector<char> &json) {
std::vector<char>::const_iterator p = json.begin();//当前的指针
ParserState state = ParserState::BEGIN;
std::list<JsonToken> tokens;//存放有效的token
//状态机自我运行中
while (state != ParserState::ERROR && p != json.end()) {
char ch = *p;
auto cur = p++;
switch (state) {
case ParserState::BEGIN: {
if (isSpace(ch)) {
//do nothing
} else if (isBeginOfValue(ch)) {
//判断是不是开始符号或者结束符号,那么就添加上去,同时状态还是这个开始状态,因为等着解析其他的字符
pushBackIfToken(tokens, ch, cur);
state = ParserState::OBJECT_OR_ARRAY_BEGIN;
} else if (ch == '"') {
//字符串
state = ParserState::STRING_BEGIN;
} else if (ch >= '0' && ch <= '9') {
tokens.emplace_back(TokenType::Double, cur);
p--;//记住,指针要向前移动
state = ParserState::NUMBER_BEGIN;
} else if (ch == '-') {
//解析负数指针不用向前移动
tokens.emplace_back(TokenType::Double, cur);
state = ParserState::NUMBER_BEGIN;
} else if (ch == 'f') {
//解析false
tokens.emplace_back(TokenType::False, cur);
state = ParserState::F_IN_FALSE;
} else if (ch == 't') {
tokens.emplace_back(TokenType::True, cur);
state = ParserState::T_IN_TRUE;
} else if (ch == 'n') {
tokens.emplace_back(TokenType::Null, cur);
state = ParserState::N_IN_NULL;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::OBJECT_OR_ARRAY_BEGIN: {
if (isSpace(ch)) {
//do nothing
} else if (isEndOfValue(ch)) {
//如果是结束符,那么下一个状态为值结束状态
pushBackIfToken(tokens, ch, cur);
state = ParserState::END;
} else {
p--;//注意要退一格
state = ParserState::BEGIN;
}
break;
}
case ParserState::N_IN_NULL: {
state = ch == 'u' ? ParserState::NU_IN_NULL : ParserState::ERROR;
break;
}
case ParserState::NU_IN_NULL: {
state = ch == 'l' ? ParserState::NUL_IN_NULL : ParserState::ERROR;
break;
}
case ParserState::NUL_IN_NULL: {
if (ch == 'l') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::T_IN_TRUE: {
state = ch == 'r' ? ParserState::TR_IN_TRUE : ParserState::ERROR;
break;
}
case ParserState::TR_IN_TRUE: {
state = ch == 'u' ? ParserState::TRU_IN_TRUE : ParserState::ERROR;
break;
}
case ParserState::TRU_IN_TRUE: {
if (ch == 'e') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::F_IN_FALSE: {
state = ch == 'a' ? ParserState::FA_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FA_IN_FALSE: {
state = ch == 'l' ? ParserState::FAL_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FAL_IN_FALSE: {
state = ch == 's' ? ParserState::FALS_IN_FALSE : ParserState::ERROR;
break;
}
case ParserState::FALS_IN_FALSE: {
if (ch == 'e') {
tokens.back().end = cur;
state = ParserState::END;
} else {
state = ParserState::ERROR;
}
break;
}
case ParserState::ESCAPE: {
//遇到转义的,回到前一个状态
state = ParserState::STRING;//转义是在字符串才有的,所以回到字符串状态
break;
}
case ParserState::STRING_BEGIN: {
tokens.emplace_back(TokenType::String, cur);//栈顶元素为字符串类型
//解析字符串
state = ParserState::STRING;
break;
}
case ParserState::STRING: {
//字符串
if (ch == '"') {
//字符串结束
//取出栈顶的元素,记录位置
tokens.back().end = cur;
state = ParserState::END;
} else if (ch == '\\') {
//转义的话
state = ParserState::ESCAPE;
}
break;
}
case ParserState::END: {
//如果是结尾的符,就一直解析,解析到不是结尾符为止
if (isSpace(ch) || isSeparator(ch) || isEndOfValue(ch)) {
pushBackIfToken(tokens, ch, cur);
} else {
//不是结尾符,那么转到开始状态,注意需要改变当前指针
p--;
state = ParserState::BEGIN;
}
break;
}
case ParserState::NUMBER_BEGIN: {
//解析数字
if (ch == '0') {
//解析0或者小数
state = ParserState::NUMBER_POINT;
} else if (ch >= '1' && ch <= '9') {
state = ParserState::NUMBER_BEFORE_POINT;//小数点之前的数字
} else {
//其他情况都是错误的
state = ParserState::ERROR;
}
break;
}
case ParserState::NUMBER_POINT: {
//遇到0开头的数字
if (ch == '.') {
//解析小数
state = ParserState::NUMBER_AFTER_POINT;//小数点之后的数字
} else if (ch == ',' || isSpace(ch) || isEndOfValue(ch)) {
tokens.back().type = TokenType::LongLong;
tokens.back().end = cur;
p--;//退一格
state = ParserState::END;
} else {
//其他情况都是不允许的
state = ParserState::ERROR;
}
break;
}
case ParserState::NUMBER_BEFORE_POINT: {
//遇到0开头的数字
if (ch >= '0' && ch <= '9') {
//do nothing
} else {
//其他情况根ZERO_NUMBER_POINT一样,不过指针需要向前移动
p--;
state = ParserState::NUMBER_POINT;//小数点之后的数字
}
break;
}
case ParserState::NUMBER_AFTER_POINT: {
//小数点前后,可以是0-9任何数字
if (ch >= '0' && ch <= '9') {
//do nothing
} else if (ch == ',' || isSpace(ch) || isEndOfValue(ch)) {
tokens.back().end = cur;
p--;//退一格
state = ParserState::END;
} else {
//其他情况都是不允许的
state = ParserState::ERROR;
}
break;
}
default:
break;
}
}
//若解析是错误的,直接返回
if (state == ParserState::ERROR) {
return JsonValue();
}
//生成jsonValue
return genJsonValueViaTokens(tokens);
}
bool JsonParser::isSpace(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
}
JsonValue JsonParser::genJsonValueViaTokens(std::list<JsonToken> &tokens) {
//先出队一个元素
JsonToken token = tokens.front();
//当前处理的是值
tokens.pop_front();
if (TokenType::ObjectBegin == token.type) {
//当前处理的是对象
return genJsonObjectViaTokens(tokens);
} else if (TokenType::ArrayBegin == token.type) {
//当前处理的是数组
return genJsonArrayViaTokens(tokens);
}
//下面的情况的值是普通类型的
if (TokenType::String == token.type) {
return JsonValue(token.start, token.end);//当前是字符串
} else if (TokenType::True == token.type) {
return JsonValue(true);//当前是布尔型
} else if (TokenType::False == token.type) {
return JsonValue(false);//当前是布尔型
} else if (TokenType::Double == token.type) {
return JsonValue(std::atof(std::string(token.start, token.end).c_str()));//当前是实数
} else if (TokenType::LongLong == token.type) {
return JsonValue(std::atoll(std::string(token.start, token.end).c_str()));//当前是实数
} else if (TokenType::Null == token.type) {
return JsonValue();
}
return JsonValue();
}
JsonValue JsonParser::genJsonArrayViaTokens(std::list<JsonToken> &tokens) {
JsonArray jsonArray;
//找到第一个']'然后不停出队
while (TokenType::ArrayEnd != tokens.front().type) {
jsonArray.append(genJsonValueViaTokens(tokens));
//如果还没有遇到]结束符队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
//然后去掉数组间的分割符
if (TokenType::MemberSeparator == tokens.front().type) {
tokens.pop_front();//','
} else if (TokenType::ArrayEnd == tokens.front().type) {
//do nothing
} else {
return JsonValue();
}
}
//循环结束后,类型为ArrayBegin,需要pop掉
tokens.pop_front();
return jsonArray;
}
JsonValue JsonParser::genJsonObjectViaTokens(std::list<JsonToken> &tokens) {
JsonObject jsonObject;
//找到第一个'}'然后不停出队
while (TokenType::ObjectEnd != tokens.front().type) {
//再出队key
JsonToken key = tokens.front();
tokens.pop_front();
//然后去掉对象间的分割符':'
if (tokens.front().type != TokenType::ObjectKeyValueSeparator) {
return false;
}
//如果还没有遇到:队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
tokens.pop_front();//':'
//再出队value
jsonObject.insert(std::string(key.start, key.end), genJsonValueViaTokens(tokens));
//如果还没有遇到}队列就空了,说明格式错误
if (tokens.empty()) {
return JsonValue();
}
//最后再去掉对象值之间的分割符
if (TokenType::MemberSeparator == tokens.front().type) {
tokens.pop_front();//','
} else if (TokenType::ObjectEnd == tokens.front().type) {
//do nothing
} else {
return JsonValue();
}
}
//循环结束后,类型为TokenType::ObjectBegin,需要pop掉
tokens.pop_front();
return jsonObject;
}
std::vector<char> JsonParser::parse(const JsonValue &root) {
std::vector<char> json;
switch (root.type()) {
case JsonValueType::Null: {
json.insert(json.end(), {'n', 'u', 'l', 'l'});
break;
}
case JsonValueType::Double: {
std::string str = std::to_string(root.toDouble());
json.insert(json.end(), str.begin(), str.end());
break;
}
case JsonValueType::LongLong: {
std::string str = std::to_string(root.toLongLong());
json.insert(json.end(), str.begin(), str.end());
break;
}
case JsonValueType::String: {
json.push_back('"');
//处理转义
for (char ch : root.toString()) {
switch (ch) {
case '\"':
json.insert(json.end(), {'\\', '\"'});
break;
case '\\':
json.insert(json.end(), {'\\', '\\'});
break;
case '\b':
json.insert(json.end(), {'\\', 'b'});
break;
case '\f':
json.insert(json.end(), {'\\', 'f'});
break;
case '\n':
json.insert(json.end(), {'\\', 'n'});
break;
case '\r':
json.insert(json.end(), {'\\', 'r'});
break;
case '\t':
json.insert(json.end(), {'\\', 't'});
break;
default:
json.push_back(ch);//其他情况不变
}
}
//结尾加上'"'
json.push_back('"');
break;
}
case JsonValueType::Boolean: {
if (root.toBoolean()) {
json.insert(json.end(), {'t', 'r', 'u', 'e'});
} else {
json.insert(json.end(), {'f', 'a', 'l', 's', 'e'});
}
break;
}
case JsonValueType::Array: {
json.push_back('[');
bool isFirst = true;
for (const auto &v : root.toArray()) {
if (isFirst) {
isFirst = false;
} else {
json.push_back(',');//不是第一次,就加上','分割符
}
std::vector<char> jsonTmp = parse(v);
json.insert(json.end(), jsonTmp.begin(), jsonTmp.end());
}
json.push_back(']');
break;
}
case JsonValueType::Object: {
json.push_back('{');
bool isFirst = true;
for (const auto &kv : root.toObject()) {
if (isFirst) {
isFirst = false;
} else {
json.push_back(',');//不是第一次,就加上','分割符
}
//找出key
std::vector<char> jsonTmp = parse(kv.first);
json.insert(json.end(), jsonTmp.begin(), jsonTmp.end());
//插入分割符
json.push_back(':');
//找出value
jsonTmp = parse(kv.second);
json.insert(json.end(), jsonTmp.begin(), jsonTmp.end());
}
json.push_back('}');
break;
}
default:
break;
}
return json;
}
bool JsonParser::isEndOfValue(char ch) {
return ch == '}' || ch == ']';
}
void JsonParser::pushBackIfToken(std::list<JsonToken> &tokens, char ch, const std::vector<char>::const_iterator &pos) {
switch (ch) {
case '{':
tokens.emplace_back(TokenType::ObjectBegin, pos);
break;
case '}':
tokens.emplace_back(TokenType::ObjectEnd, pos);
break;
case '[':
tokens.emplace_back(TokenType::ArrayBegin, pos);
break;
case ']':
tokens.emplace_back(TokenType::ArrayEnd, pos);
break;
case ':':
tokens.emplace_back(TokenType::ObjectKeyValueSeparator, pos);
break;
case ',':
tokens.emplace_back(TokenType::MemberSeparator, pos);
break;
default:
break;
}
}
bool JsonParser::isSeparator(char ch) {
return ch == ':' || ch == ',';
}
bool JsonParser::isBeginOfValue(char ch) {
return ch == '{' || ch == '[';
}
说明:上面有一个需要注意的是,对于JsonValue转为JSON字符串,如果是字符串类型,遇到一些特殊字符[ ‘\r’, ‘\n’, ‘"’ …],需要做转义,否则会导致json字符串有错误。
五:测试
main.cpp
#include <iostream>
#include "jsonparser.h"
int main() {
std::vector<char> jsonStr;
JsonObject jsonObj;
std::string str = "{ \"你好\":{ \"I\\\"NT\":122,\"NULL\":null , \"FALSE\": false, \"TRUE\": true},\"k1\":\"v1\",\"k2\" : \"v2\",\"k3\" : {\"j1\":\"j2\"}, \"k4\":[\"1\",{\"k2\":\"k1\"},\"3\",\"4\", { } ,[],{\"1\":1},[1],[-200],[1.222222]] }";
//std::string str = "[\"1\",{\"k2\":\"k1\"},\"3\",\"4\",[]]";
//std::string str = "[1]";
std::vector<char> json(str.begin(), str.end());
JsonValue root = JsonParser::parse(json);
jsonStr = JsonParser::parse(root);
jsonStr.push_back('\0');
std::cout << jsonStr.data() << std::endl;
//字符串转义
jsonObj.insert("1234\"", JsonValue());
jsonStr = JsonParser::parse(jsonObj);
jsonStr.push_back('\0');
std::cout << jsonStr.data() << std::endl;
return 0;
}
输出结果如下:
{"k1":"v1","k2":"v2","k3":{"j1":"j2"},"k4":["1",{"k2":"k1"},"3","4",{},[],{"1":1},[1],[-200],[1.222222]],"你好":{"FALSE":false,"I\\\"NT":122,"NULL":null,"TRUE":true}}
{"1234\"":null}
Ⅱ:普通对象JSON序列化篇
一:说明
我对对象序列化和反序列化的理解很简单,就是将对象转化为能够存储和传输的一串东西,同时这串东西也能转换回这个对象。现在比较流行的是将对象转换为JSON字符串,然后将这个字符串在网络上进行传输,以便对端通过解析JSON字符串,能够读懂请求要做的事情。
本文主要基于前面说到的字符串解析为JSON对象,来做到将一个普通对象转换为JSON字符串的效果。
二:准备工作
首先,对于一个普通的C++对象转换为JSON字符串,我们希望能够达到的效果是:
- 只提供一个宏,这个宏尽量使用简单,最好是我需要什么成员序列化,我就只提供什么成员的名称,不需要再提高别的什么东西了。
- 不污染原先的结构体或者类的定义,最好能定义在类外。
1:为了达到第一个效果,我们对于类中需要序列化的成员,首先需要获取成员的名称和成员的地址,因为只有知道成员的名称和成员的地址,才能够通过这些信息,来做到将JSON对象和C++普通对象一一对应起来。我们可以通过宏来简化,能够达到如下效果就好:
struct ABC {
int i;
std::string s;
std::map<int, CFF> m;
std::vector<int> j;
long long f;
CFF aaa;
};
Serialization(ABC, i, s, j, f, m, aaa)
其中宏Serialization的主要作用是将类中成员的地址和成员的方法提取出来,我们将它合在一起,放在std::pair中,而由于类中的成员是不定个数和不定参数类型的,我们就需要将其放入万能类型std::tuple中,接下来就是对这个std::tuple进行操作了。我们之后再对std::tuple的内容进行解析,将这个普通对象A组装为JsonObject对象的时候,可以通过成员的地址,获取到成员的内容以及成员的类型,然后将他递归insert进去JsonObject中,key便是该成员的名称。反之,我们如果得到一个JsonObject,可以通过它的每一个key,去匹配到对应的这个普通对象A的成员,匹配到这个成员之后,我们也知道了这个成员的地址p和类型,我们就可以通过这个类型去解析这个JsonValue,然后将解析到的值赋到地址p中,这就完成了json的反序列化。
2:为了达到第二个效果,我们需要想出一种方法,来将类中的一些信息在类外定义。这里我们用到我之前一篇文章也用到的技巧。也就是模板类。如果感兴趣,可以查看C++11 mysql数据库从原生api的封装到ORM库的实现 [高仿通用mapper接口]
本文的模板类定义如下:
/**
* 对象序列化
*/
template<typename T>
struct Serializable {
/**
* 序列化一个对象
* @return
*/
static JsonValue serialize(const T &t) { return JsonValue(); }
/**
* 反序列化为对象
* @param jsonObj
* @return
*/
static T deserialize(const JsonObject &jsonObject) { return T(); }
};
3:综合以上说明,我们可以将宏Serialization内容展开定义为如下形式:
template<>
struct Serializable<Class> {
static JsonObject serialize(const Class &t) { return JsonHelper::serialize(std::make_tuple(Func)); }
static Class deserialize(const JsonObject &jsonObject) { Class t; JsonHelper::deserialize(std::make_tuple(Func), jsonObject); return t; }
};
4:然后就可以通过宏中传入的对象的成员名称和成员地址信息,运用1中的方法对tuple进行操作,达到最后序列化和反序列化对象的效果了。
三:详细代码
主要用到了宏展开的相关操作,以及模板的操作。如果对这方便不太清楚的,可以搜索模板元编程,以及宏展开的相关知识。
serialization.h
#ifndef CANDY_SERIALIZATION_H
#define CANDY_SERIALIZATION_H
#include "jsonparser.h"
#include <sstream>
#include <string.h>
#define ARG_EXPAND(...) __VA_ARGS__
#define ARG_1(arg, ...) std::make_pair(std::string(#arg),&t.arg)
#define ARG_2(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_1(__VA_ARGS__))
#define ARG_3(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_2(__VA_ARGS__))
#define ARG_4(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_3(__VA_ARGS__))
#define ARG_5(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_4(__VA_ARGS__))
#define ARG_6(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_5(__VA_ARGS__))
#define ARG_7(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_6(__VA_ARGS__))
#define ARG_8(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_7(__VA_ARGS__))
#define ARG_9(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_8(__VA_ARGS__))
#define ARG_10(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_9(__VA_ARGS__))
#define ARG_11(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_10(__VA_ARGS__))
#define ARG_12(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_11(__VA_ARGS__))
#define ARG_13(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_12(__VA_ARGS__))
#define ARG_14(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_13(__VA_ARGS__))
#define ARG_15(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_14(__VA_ARGS__))
#define ARG_16(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_15(__VA_ARGS__))
#define ARG_17(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_16(__VA_ARGS__))
#define ARG_18(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_17(__VA_ARGS__))
#define ARG_19(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_18(__VA_ARGS__))
#define ARG_20(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_19(__VA_ARGS__))
#define ARG_21(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_20(__VA_ARGS__))
#define ARG_22(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_21(__VA_ARGS__))
#define ARG_23(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_22(__VA_ARGS__))
#define ARG_24(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_23(__VA_ARGS__))
#define ARG_25(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_24(__VA_ARGS__))
#define ARG_26(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_25(__VA_ARGS__))
#define ARG_27(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_26(__VA_ARGS__))
#define ARG_28(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_27(__VA_ARGS__))
#define ARG_29(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_28(__VA_ARGS__))
#define ARG_30(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_29(__VA_ARGS__))
#define ARG_31(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_30(__VA_ARGS__))
#define ARG_32(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_31(__VA_ARGS__))
#define ARG_33(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_32(__VA_ARGS__))
#define ARG_34(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_33(__VA_ARGS__))
#define ARG_35(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_34(__VA_ARGS__))
#define ARG_36(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_35(__VA_ARGS__))
#define ARG_37(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_36(__VA_ARGS__))
#define ARG_38(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_37(__VA_ARGS__))
#define ARG_39(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_38(__VA_ARGS__))
#define ARG_40(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_39(__VA_ARGS__))
#define ARG_41(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_40(__VA_ARGS__))
#define ARG_42(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_41(__VA_ARGS__))
#define ARG_43(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_42(__VA_ARGS__))
#define ARG_44(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_43(__VA_ARGS__))
#define ARG_45(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_44(__VA_ARGS__))
#define ARG_46(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_45(__VA_ARGS__))
#define ARG_47(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_46(__VA_ARGS__))
#define ARG_48(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_47(__VA_ARGS__))
#define ARG_49(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_48(__VA_ARGS__))
#define ARG_50(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_49(__VA_ARGS__))
#define ARG_51(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_50(__VA_ARGS__))
#define ARG_52(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_51(__VA_ARGS__))
#define ARG_53(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_52(__VA_ARGS__))
#define ARG_54(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_53(__VA_ARGS__))
#define ARG_55(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_54(__VA_ARGS__))
#define ARG_56(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_55(__VA_ARGS__))
#define ARG_57(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_56(__VA_ARGS__))
#define ARG_58(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_57(__VA_ARGS__))
#define ARG_59(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_58(__VA_ARGS__))
#define ARG_60(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_59(__VA_ARGS__))
#define ARG_61(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_60(__VA_ARGS__))
#define ARG_62(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_61(__VA_ARGS__))
#define ARG_63(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_62(__VA_ARGS__))
#define ARG_64(arg, ...) std::make_pair(std::string(#arg),&t.arg),ARG_EXPAND(ARG_63(__VA_ARGS__))
#define RSEQ_N() 64,63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, _64, N, ...) N
#define ARG_COUNT_INNER(...) ARG_EXPAND(ARG_N(__VA_ARGS__))
#define GET_ARG_COUNT(...) ARG_COUNT_INNER(__VA_ARGS__,RSEQ_N())
#define ARG_LIST(N, arg, ...) ARG##_##N(arg,__VA_ARGS__)
#define GEN_FUNC(N, ...) ARG_EXPAND(ARG_LIST(N, __VA_ARGS__))
#define SERIALIZATION_INNER(Class, Func) \
template<> \
struct Serializable<Class> { \
static JsonObject serialize(const Class &t) { return JsonHelper::serialize(std::make_tuple(Func)); } \
static Class deserialize(const JsonObject &jsonObject) { Class t; JsonHelper::deserialize(std::make_tuple(Func), jsonObject); return t; } \
};
/**
* Class 类名
* ... 字段名
*/
#define Serialization(Class, ...) SERIALIZATION_INNER(Class, GEN_FUNC(GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__))
/**
* 对象序列化
*/
template<typename T>
struct Serializable {
/**
* 序列化一个对象
* @return
*/
static JsonValue serialize(const T &t) { return JsonValue(); }
/**
* 反序列化为对象
* @param jsonObj
* @return
*/
static T deserialize(const JsonObject &jsonObject) { return T(); }
};
class JsonHelper {
private:
template<typename Tuple, size_t N>
struct JsonObjectParser {
/**
* 转换为json对象
* @param fieldTuple
* @param jsonObject
*/
static void toJsonObject(const Tuple &fieldTuple, JsonObject &jsonObject) {
JsonObjectParser<Tuple, N - 1>::toJsonObject(fieldTuple, jsonObject);
auto data = std::get<N - 1>(fieldTuple);
std::string key = data.first;
auto value = *data.second;
jsonObject.insert(key, toJsonValue(value));
}
/**
* 从json对象中转换回来
* @param fieldTuple
* @param jsonObject
*/
static void fromJsonObject(const Tuple &fieldTuple, const JsonObject &jsonObject) {
JsonObjectParser<Tuple, N - 1>::fromJsonObject(fieldTuple, jsonObject);
auto data = std::get<N - 1>(fieldTuple);
std::string key = data.first;
if (jsonObject.contains(key)) {
fromJsonValue(data.second, jsonObject[key]);
}
}
};
template<typename Tuple>
struct JsonObjectParser<Tuple, 1> {
static void toJsonObject(const Tuple &fieldTuple, JsonObject &jsonObject) {
auto data = std::get<0>(fieldTuple);
std::string key = data.first;
auto value = *data.second;
jsonObject.insert(key, toJsonValue(value));
}
static void fromJsonObject(const Tuple &fieldTuple, const JsonObject &jsonObject) {
auto data = std::get<0>(fieldTuple);
std::string key = data.first;
if (jsonObject.contains(key)) {
fromJsonValue(data.second, jsonObject[key]);
}
}
};
public:
工具
template<typename T>
static void convertFromString(const std::string &str, T &v) {
std::stringstream ss;
ss << str;
ss >> v;
}
static void convertFromString(const std::string &str, std::string &v) { v = str; }
template<typename T>
static void convertToString(const T &v, std::string &str) {
std::stringstream ss;
ss << v;
ss >> str;
}
static void convertToString(const std::string &v, std::string &str) { str = v; }
public:
//从jsonValue中转换过来
单值
static void fromJsonValue(int *field, const JsonValue &jsonValue) {
*field = (int) jsonValue.toLongLong();
}
static void fromJsonValue(std::string *field, const JsonValue &jsonValue) {
*field = jsonValue.toString();
}
static void fromJsonValue(bool *field, const JsonValue &jsonValue) {
*field = jsonValue.toBoolean();
}
static void fromJsonValue(long long *field, const JsonValue &jsonValue) {
*field = jsonValue.toLongLong();
}
static void fromJsonValue(double *field, const JsonValue &jsonValue) {
*field = jsonValue.toDouble();
}
template<typename T>
static void fromJsonValue(T *field, const JsonValue &jsonValue) {
*field = Serializable<T>::deserialize(jsonValue.toObject());
}
泛型值
template<typename T>
static void fromJsonValue(std::vector<T> *field, const JsonValue &jsonValue) {
for (const auto &v:jsonValue.toArray()) {
T t;
fromJsonValue(&t, v);
field->push_back(t);
}
}
template<typename T>
static void fromJsonValue(std::list<T> *field, const JsonValue &jsonValue) {
for (const auto &v:jsonValue.toArray()) {
T t;
fromJsonValue(&t, v);
field->push_back(t);
}
}
template<typename K, typename V>
static void fromJsonValue(std::map<K, V> *field, const JsonValue &jsonValue) {
for (const auto &kv : jsonValue.toObject()) {
K k;
convertFromString(kv.first, k);
V v;
fromJsonValue(&v, kv.second);
field->insert(std::make_pair(k, v));
}
}
public:
//转换为JsonValue
单值
static JsonValue toJsonValue(bool value) {
return JsonValue(value);
}
static JsonValue toJsonValue(long long value) {
return JsonValue(value);
}
static JsonValue toJsonValue(int value) {
return JsonValue(value);
}
static JsonValue toJsonValue(const std::string &value) {
return JsonValue(value);
}
static JsonValue toJsonValue(double value) {
return JsonValue(value);
}
template<typename T>
static JsonValue toJsonValue(const T &value) {
return Serializable<T>::serialize(value);
}
范型值
template<typename T>
static JsonValue toJsonValue(const std::list<T> &values) {
JsonArray jsonArray;
for (const auto &v : values) {
jsonArray.append(toJsonValue(v));
}
return jsonArray;
}
template<typename T>
static JsonValue toJsonValue(const std::vector<T> &values) {
JsonArray jsonArray;
for (const auto &v : values) {
jsonArray.append(toJsonValue(v));
}
return jsonArray;
}
template<typename K, typename V>
static JsonValue toJsonValue(const std::map<K, V> &values) {
JsonObject jsonObject;
for (const auto &kv : values) {
std::string key;
convertToString(kv.first, key);//key需要转为字符串
jsonObject.insert(key, toJsonValue(kv.second));
}
return jsonObject;
}
public:
template<typename... Args>
static JsonObject serialize(const std::tuple<Args...> &fieldTuple) {
JsonObject jsonObject;
JsonObjectParser<decltype(fieldTuple), sizeof...(Args)>::toJsonObject(fieldTuple, jsonObject);
return jsonObject;
}
template<typename... Args>
static void deserialize(const std::tuple<Args...> &fieldTuple, const JsonObject &jsonObject) {
JsonObjectParser<decltype(fieldTuple), sizeof...(Args)>::fromJsonObject(fieldTuple, jsonObject);
}
};
#endif //CANDY_SERIALIZATION_H
四:测试
main.cpp
#include <iostream>
#include "serialization.h"
struct CFF {
double d;
CFF() {}
CFF(double d) : d(d) {}
};
Serialization(CFF, d)
struct ABC {
int i;
std::string s;
std::map<int, CFF> m;
std::vector<int> j;
long long f;
CFF aaa;
};
Serialization(ABC, i, s, j, f, m, aaa)
int main() {
std::vector<char> jsonStr;
JsonObject jsonObj;
ABC abc;
abc.j = {1, 2, 3, 4};
abc.i = 100;
abc.m[1] = CFF(9.99);
abc.m[10] = CFF(20);
abc.aaa.d = 9.99;
abc.f = 99991111;
abc.s = "hello-world";
jsonObj = Serializable<ABC>::serialize(abc);
jsonStr = JsonParser::parse(jsonObj);
jsonStr.push_back('\0');
std::cout << jsonStr.data() << std::endl;
ABC t = Serializable<ABC>::deserialize(jsonObj);
jsonObj = Serializable<ABC>::serialize(t);
jsonStr = JsonParser::parse(jsonObj);
jsonStr.push_back('\0');
std::cout << jsonStr.data() << std::endl;
return 0;
}
输出结果如下:
{"aaa":{"d":9.990000},"f":99991111,"i":100,"j":[1,2,3,4],"m":{"1":{"d":9.990000},"10":{"d":20.000000}},"s":"hello-world"}
{"aaa":{"d":9.990000},"f":99991111,"i":100,"j":[1,2,3,4],"m":{"1":{"d":9.990000},"10":{"d":20.000000}},"s":"hello-world"}
Ⅲ:总结
学无止境