cocos2d-x3.x使用rapidjson

时间:2023-02-07 23:19:32

 

rapidjson效率高,所以之前cocostudio里面解析用的jsoncpp也换成了rapidjson。

引擎又带有rapidjson库,所以不用单独去下载,直接就可以用。

 

这里主要写一下关于解析和存储的代码笔记。

 

1. 解析

#include "json/rapidjson.h"
#include "json/document.h"
#include "json/writer.h"
#include "json/stringbuffer.h"

#define FILE_Name "EmailInfo.txt"

#define KEY_Root       "EmailList"
#define KEY_Id             "id"
#define KEY_Type          "type"
#define KEY_Content        "content"
#define KEY_BonusId        "bonus_unitID"
#define KEY_BonusCount    "bonusCount"
#define KEY_IsRead         "isAlreadyRead"
#define KEY_RecvTime      "recvTime"

//将要解析的json格式
// {
//     "EmailList":[
//         {
//             "id":1,
//             "type":1,
//             "content":"string",
//             "bonus_unitID":99,
//             "bonusCount":10,
//             "isAlreadyRead":false,
//             "recvTime":11111
//         }
//     ]
// }


//解析函数
bool EmailHelper::initData()
{
    string filePath = FileUtils::getInstance()->getWritablePath();
    filePath += FILE_Name;
    Data dat = FileUtils::getInstance()->getDataFromFile(filePath);
    if (dat.getSize() <= 0)
    {
        // no file 
        CCLOG("%s ---> no file [%s]", __FUNCTION__, filePath.c_str());
        return false;
    }
    char *buf = new char[dat.getSize()+1];
    strncpy(buf, (char*)dat.getBytes(), dat.getSize());
    buf[dat.getSize()] = 0;  //重新分配内存就是为了这一步,否则直接用Data来解析会解析错误。
    CCLOG("%s ---> %s\n", __FUNCTION__, buf);

    rapidjson::Document d;
    d.Parse<0>(buf);
    delete [] buf;
    if (d.HasParseError())  //解析错误
    {
        CCLOG("%s ---> GetParseError %s\n", __FUNCTION__, d.GetParseError());
        return false;
    }
    else if (d.IsObject()) 
    {
        if (d.HasMember(KEY_Root) && d[KEY_Root].IsArray()/* && d[KEY_Root].Size() > 0*/)
        {
            const rapidjson::Value& arr = d[KEY_Root];
            for (int i=0,count=arr.Size(); i<count; ++i)
            {
                Email temp;
                if (arr[i].HasMember(KEY_Id)) temp.id = arr[i][KEY_Id].GetUint();
                if (arr[i].HasMember(KEY_Type)) temp.type = (Email::EmailType)arr[i][KEY_Type].GetUint();
                if (arr[i].HasMember(KEY_Content)) temp.content = arr[i][KEY_Content].GetString();
                if (arr[i].HasMember(KEY_BonusId)) temp.bonus_unitID = arr[i][KEY_BonusId].GetUint();
                if (arr[i].HasMember(KEY_BonusCount)) temp.bonusCount = arr[i][KEY_BonusCount].GetUint();
                if (arr[i].HasMember(KEY_IsRead)) temp.isAlreadyRead = arr[i][KEY_IsRead].GetBool();
                if (arr[i].HasMember(KEY_RecvTime)) temp.recvTime = arr[i][KEY_RecvTime].GetInt();
                m_vecEmailList.push_back(temp);
            }
            return true;
        }
    }

    return false;
}

 

2. 存储

bool EmailHelper::saveData()
{
    rapidjson::Document document;
    document.SetObject(); //Set this value as an empty object.
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
    //value
    rapidjson::Value emailArr(rapidjson::kArrayType);
    for (int i=0,count=m_vecEmailList.size(); i<count; ++i)
    {
        rapidjson::Value object(rapidjson::kObjectType);
        object.AddMember<unsigned int>(KEY_Id, m_vecEmailList[i].id, allocator);
        object.AddMember<unsigned int>(KEY_Type, m_vecEmailList[i].type, allocator);
        object.AddMember<const char*>(KEY_Content, m_vecEmailList[i].content.c_str(), allocator);
        object.AddMember<unsigned int>(KEY_BonusId, m_vecEmailList[i].bonus_unitID, allocator);
        object.AddMember<unsigned int>(KEY_BonusCount, m_vecEmailList[i].bonusCount, allocator);
        object.AddMember<bool>(KEY_IsRead, m_vecEmailList[i].isAlreadyRead, allocator);
        object.AddMember<int>(KEY_RecvTime, m_vecEmailList[i].recvTime, allocator);
        emailArr.PushBack(object, allocator);
    }
    document.AddMember(KEY_Root, emailArr, allocator);

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    document.Accept(writer);


    string filePath = FileUtils::getInstance()->getWritablePath();
    filePath += FILE_Name;
    FILE* fp = fopen(FileUtils::getInstance()->fullPathForFilename(filePath).c_str(),"w+");//具有读写属性,写的时候如果文件存在,会被清空,从头开始写。
    if (!fp)
    {
        CCASSERT(fp,"file open faild!");
        return false;
    }
    fwrite(buffer.GetString(),sizeof(char),buffer.Size(),fp);
    fclose(fp);

    CCLOG("%s %s ---> %s", __FUNCTION__, filePath.c_str(), buffer.GetString());
    return true;
}