C++ 揭开JSON序列化的奥秘----从协议解析到普通对象JSON序列化底层原理的解析与实现

本文详细介绍了如何使用C++实现JSON格式的解析和序列化。首先,通过有限状态自动机解析JSON字符串成Token,然后递归组装成JsonValue对象。接着,展示了如何将普通C++对象转换为JSON字符串,利用宏展开和模板元编程,实现了序列化和反序列化。最后,提供了测试代码验证了整个流程的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ⅰ:格式解析篇

一:JSON格式解析初步

我们都知道JSON格式是怎么样的,在这里我们不详细说明JSON的格式,如果需要查看更详细的介绍,可以去JSON中国网站查询。在这里,我们只介绍JSON格式的解析过程。

那么,要解析JSON格式,我们到底需要怎么做呢?本文主要分两步:

  1. 找有效字符:抽出JSON字符串中的有效字符,我们叫它Token,并且如果符合条件的话,就将它们一个个入队。
  2. 组合JsonValue对象:每次出队一个有效字符Token,通过有效字符的类型[对象/数组/单值],递归组合JsonValue对象。

二:Token解析

根据上述的步骤,首先我们需要找出Json字符串中的Token。那么token都有哪些?主要有如下几个:

token名称描述
ObjectBegin对象开始
ObjectEnd对象结束
ArrayBegin数组开始
ArrayEnd数组结束
ObjectKeyValueSeparator对象键值对的分割符,也就是’:’
MemberSeparator成员分割符,也就是’,’
String字符串
Double实数
LongLong整型
Truetrue值
Falsefalse值
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_NULLnull中的n
NU_IN_NULLnull中的nu
NUL_IN_NULLnull中的nul
T_IN_TRUEtrue中的t
TR_IN_TRUEtrue中的tr
TRU_IN_TRUEtrue中的tru
F_IN_FALSEfalse中的f
FA_IN_FALSEfalse中的fa
FAL_IN_FALSEfalse中的fal
FALS_IN_FALSEfalse中的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结构天然是一个递归结构,所以不出意外,本文也是主要运用递归算法来组装。递归思想的步骤也很简单:

  1. 出队一个Token
  2. 遇到ObjectBegin类型,表示需要解析对象了,转步骤5
  3. 遇到ArrayBegin类型,表示需要解析数组了,就去递归解析数组,直达遇到单值类型
  4. 遇到单值类型[String,True,False,Double,LongLong,Null]的时候,直接解析出它们的值,存到JsonValue中,结束本次递归。
  5. 递归循环解析对象中的每一个key和value,依次先出队一个key,再出队一个ObjectKeyValueSeparator[ ‘:’ ],再递归解析出一个value,组装到JsonValue中
  6. 递归循环解析数组中的每一个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. 只提供一个宏,这个宏尽量使用简单,最好是我需要什么成员序列化,我就只提供什么成员的名称,不需要再提高别的什么东西了。
  2. 不污染原先的结构体或者类的定义,最好能定义在类外。

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"}

Ⅲ:总结

学无止境

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值