rapidjson库示例及函数封装

开发工作中涉及JSON文件的解析/编码是不可避免的,象PHP/JAVA/C#等语言中都内置有非常方便的JSON操作类库,但C++自身没有提供这样的操作方法,因此不得不借助一些第三方库来完成JSON操作。之前使用过jsoncpp,感觉不是太好,对于一些含有特殊字符的json内容解析时还可能发生程序崩溃,后来接触到RadpidJSON,发现非常不错,据官方宣称是最快的JSON库,所以称之为"RAPID"。

下面是本人在工作中封装的工具函数,使用非常方便,能够满足大多数情况下JSON操作的需要,能够大节省我们的编码时间。

struct TStrMapVec
{
    vector<map<string, string>> vec_;
};

struct TJsonParseResult
{
public:
    bool FindParam(const std::string& key)
    {
        std::string name(key);
        std::transform(name.begin(), name.end(), name.begin(), ::tolower);

        auto it = m_mapParams.find(name);
        if (it != m_mapParams.end())
        {
            return true;
        }

        auto it1 = m_mapArray.find(name);
        if (it1 != m_mapArray.end())
        {
            return true;
        }

        return false;
    }

    std::string GetParam(const std::string& key)
    {
        std::string name(key);
        std::transform(name.begin(), name.end(), name.begin(), ::tolower);

        std::string value;
        auto it = m_mapParams.find(name);
        if (it != m_mapParams.end())
        {
            value = it->second;
        }
        return value;
    }

    void GetArrayParam(const std::string& key, std::vector<std::map<std::string, std::string>>& vecParams)
    {
        std::string name(key);
        std::transform(name.begin(), name.end(), name.begin(), ::tolower);

        auto it = m_mapArray.find(name);
        if (it != m_mapArray.end())
        {
            vecParams = it->second.vec_;
        }
    }

    void AddParam(const std::string& key, const std::string& value)
    {
        std::string name(key);
        std::transform(name.begin(), name.end(), name.begin(), ::tolower);
        m_mapParams[name] = value;
    }

    void AddArrayParam(const std::string& key, std::map<std::string, std::string>& mapParams)
    {
        std::string name(key);
        std::transform(name.begin(), name.end(), name.begin(), ::tolower);
        m_mapArray[name].vec_.push_back(mapParams);
    }

    void RemoveParam(std::string name)
    {
        m_mapParams.erase(name);
        m_mapArray.erase(name);
    }

    bool IsEmpty()
    {
        return m_mapParams.empty() && m_mapArray.empty();
    }

public:
    map<string, string> m_mapParams;    
    map<string, TStrMapVec> m_mapArray;
};

static void ParseJsonObj(const rapidjson::Value& jsonObj, TJsonParseResult& zjapiRes, string namePrefix = "")
{
    if (jsonObj.IsNull()
        || jsonObj.IsObject() == false)
    {
        return;
    }

    for (auto it = jsonObj.MemberBegin(); it != jsonObj.MemberEnd(); ++it)
    {
        auto key = it->name.GetString();
        const rapidjson::Value& jsonValue = it->value;
        string name = namePrefix;
        string value;

        if (name.empty() == false)
        {
            name += ".";
        }
        name += key;

        if (jsonValue.IsString()
            || jsonValue.IsNumber())
        {
            if (jsonValue.IsString())
            {
                value = jsonValue.GetString();
            }
            else if (jsonValue.IsInt())
            {
                value = to_string(jsonValue.GetInt());
            }
            else if (jsonValue.IsUint())
            {
                value = to_string(jsonValue.GetUint());
            }
            else if (jsonValue.IsInt64())
            {
                value = to_string(jsonValue.GetInt64());
            }
            else if (jsonValue.IsUint64())
            {
                value = to_string(jsonValue.GetUint64());
            }
            else if (jsonValue.IsDouble())
            {
                value = to_string(jsonValue.GetDouble());
            }

            zjapiRes.AddParam(name, value);
        }
        else if (jsonValue.IsArray())
        {
            //假定为数组时,数组元素只能是类似于{"a":1,"b":2}这样不再包含子数组
            map<string, string> mapParams;
            for (size_t i = 0; i < jsonValue.Size(); i++)
            {
                const rapidjson::Value& arrItem = jsonValue[i];
                if (arrItem.IsNull()
                    || arrItem.IsObject() == false)
                {
                    continue;
                }

                auto jsonText = std::move(JsonToString(arrItem));
                mapParams["json"] = jsonText;

                for (auto itItemMember = arrItem.MemberBegin(); itItemMember != arrItem.MemberEnd(); ++itItemMember)
                {
                    auto itemMemberKey = itItemMember->name.GetString();
                    const rapidjson::Value& jsonItemMemberValue = itItemMember->value;

                    if (jsonItemMemberValue.IsString())
                    {
                        mapParams[itemMemberKey] = jsonItemMemberValue.GetString();
                    }
                    else if (jsonItemMemberValue.IsInt())
                    {
                        mapParams[itemMemberKey] = to_string(jsonItemMemberValue.GetInt());
                    }
                    else if (jsonItemMemberValue.IsUint())
                    {
                        mapParams[itemMemberKey] = to_string(jsonItemMemberValue.GetUint());
                    }
                    else if (jsonItemMemberValue.IsInt64())
                    {
                        mapParams[itemMemberKey] = to_string(jsonItemMemberValue.GetInt64());
                    }
                    else if (jsonItemMemberValue.IsUint64())
                    {
                        mapParams[itemMemberKey] = to_string(jsonItemMemberValue.GetUint64());
                    }
                    else if (jsonItemMemberValue.IsArray())
                    {
                        mapParams[itemMemberKey] = std::move(JsonToString(jsonItemMemberValue));
                    }
                }

                zjapiRes.AddArrayParam(name, mapParams);
            }
        }
        else if (jsonValue.IsObject())
        {
            ParseJsonObj(jsonValue, zjapiRes, name);
        }
    }
}

//JSON解析工具函数
void ParseJson(const std::string& jsonRes, TJsonParseResult& jsonparseresult)
{
    rapidjson::Document jsonDoc;
    jsonDoc.Parse<0>(jsonRes.c_str());
    if (jsonDoc.HasParseError())
    {
        rapidjson::ParseErrorCode code = jsonDoc.GetParseError();
        return;
    }

    ParseJsonObj(jsonDoc, jsonparseresult);
}

比如对于json内容{"a":1,"b":2},调用ParseJson后,输出参数jsonparseresult的map中存在2个元素:
"a" => 1, "b" => 2

发表评论

电子邮件地址不会被公开。 必填项已用*标注