jsoncpp動態解析節點類型


   在互聯網無處不在的今天,JSON作為輕量級數據存儲格式,被廣泛應用到互聯網數據傳輸中。眾所周知,JSON由鍵/值對、對象、數組組成,其中鍵/值對的值包括以下幾種類型:

enum ValueType {
  nullValue = 0, ///< 'null' value
  intValue,      ///< signed integer value
  uintValue,     ///< unsigned integer value
  realValue,     ///< double value
  stringValue,   ///< UTF-8 string value
  booleanValue,  ///< bool value
  arrayValue,    ///< array value (ordered list)
  objectValue    ///< object value (collection of name/value pairs).
};

  如果在發送方和接收方間約定JSON數據格式中數據類型固定不變,那么不存在需要動態去判斷節點數據類型並解析的問題。但是在實際應用過程中,存在兩種情況需要支持JSON數據類型動態解析:第一,發送方因為平台遷移等種種原因導致的數據類型變化,比如本來為"key":200的鍵值對變成了"key":"200",這個時候如果還是按照intValue去獲取key的值的話,就會解析失敗; 第二,接收方不願意一個個去按照數據類型去解析JSON數據的時候,想動態去獲取數據,比如"key":20,按照stringValue和intValue都能正確的解析。

  針對以上情況,本文基於jsoncpp設計了一個動態解析JSON數據的類,主要包括兩個函數:

DynamicGetValue:支持解析int,uint,double,bool以及前三種類型的stringValue形式,當遇到"key":"1.23"鍵值對后,該函數就會進入Json::stringValue語句,通過atof函數保持了數據的精度
DynamicGetStrValue:支持解析stringValue類型以及DynamicGetValue函數支持的數據類型,在調用DynamicGetValue模板函數時,是使用的double實例化,目的是為了保證不丟失數據精度
template<typename T>
bool DynamicGetValue(Json::Value &value, T &&sValue){ //獲取json int、uint、bool、double類型的值的值
    bool result = true;
    switch(value.type()){
    case Json::stringValue:
        sValue = atof(value.asString().c_str());
        break;
    case Json::int64Value:
        sValue = value.asInt();
        break;
    case Json::uint64Value:
        sValue = value.asUInt();
        break;
    case Json::booleanValue:
        sValue = value.asBool();
        break;
    case Json::realValue:
        sValue = value.asDouble();
        break;
    default:
        result = false;
        break;
    }
    return result;
}


bool DynamicGetStrValue(Json::Value &value,string &sValue){ //獲取json string、int、uint、bool、double的值 bool result = true; double nValue = -1; if(value.type() == Json::stringValue){ sValue = value.asString(); } else if(DynamicGetValue<double&>(value, nValue)){ sprintf((char*)sValue.data(),"%.8f", nValue); } else{ result = false; } return result;
}

   針對上動態數據類型解析函數,設計了如下測試試用例,這里我們把strJson數據中的"data1":1,"data2":3.1415927兩個鍵值對當做stringValue類型來解析,能夠正確的獲取數據。但是切記,不能將"msg"和"code"調用DynamicGetValue解析,因為它們只能用stringValue來表達,只能調用DynamicGetStrValue解析,所以這里DynamicGetStrValue是萬能的,能解析任何類型的數據。

int main(){
    string strJson = "{\"msg\":\"正常\", \"code\":\"A0000\", \"data1\":1,\"data2\":3.1415927, \"data3\":-4}";
    Json::Reader reader;
    Json::Value root;
    Json::Value value;
    if (!reader.parse(strJson, root, false))
    {
        return;
    }
    string msg_,code_,strValue1,strValue2;
    unsigned int data1;
    double data2;
    int data3;
    if(root.isMember("msg")){
        value = root["msg"];
        DynamicGetStrValue(value,msg_);
    }
    if(root.isMember("code")){
        value = root["code"];
        DynamicGetStrValue(value,code_);
    }
    if(root.isMember("data1")){
        value = root["data1"];
        DynamicGetValue(value,data1);
    }
    if(root.isMember("data2")){
        value = root["data2"];
        DynamicGetStrValue(value,strValue1);
    }
    if(root.isMember("data3")){
        value = root["data3"];
        DynamicGetStrValue(value, strValue2);
    }
    char strVal[100]={0}    ;
    sprintf(strVal,"%s, %s, %d, %s, %s", msg_.c_str(), code_.c_str(), data1, strValue1.c_str(), strValue2.c_str());
    return 1;
}    

   上測試用例輸出如下圖,正確的獲取了data1和data2的值,達到了動態解析JSON數據類型的目的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM