2017-08-01 121 views
1

問題很簡單。一些JSon數據與服務器交換。 由於通信是相當複雜的,我需要日誌,複雜的信息成爲可能,看是否:使用jsoncpp時從JSon中去除私人數據的最佳方法

  • 服務器發送這是由代碼
  • JSON有錯字已於
  • 發送
  • ANS所以省略了新的價值

但是與此同時,任何私人數據都應該被虛擬數據所遮蔽。

所以不是看到日誌:

{ 
    "secuityToken" : "asdasdgas234fsdfsaD", 
    "message" : "user private message" 
} 

這樣的事情應該可以看出:

{ 
    "secuityToken" : "********", 
    "message" : "*******" 
} 

我的代碼是C++所以jsoncpp正在使用中。我可以看到 最佳arproach是:

bool ProcessServerMessage(const std::string& message) 
{ 
    Json::Value jsonValue; 
    Json::Reader reader; 
    if (reader.parse(sMessage, jsonValue, false)) 
    { 
     auto logValue = ShadowPrivateData(jsonValue, listOfKeysWithPrivateData); 
     LOG() << " JSOn recived: " << logValue; 
     … 
    } 

問題如何ShadowPrivateData應該是什麼樣子,是最通用的?

+0

而不是'container_t listOfKeysWithPrivateData'對於'std :: function isKeyPrivate'(或該模板參數) – Caleth

+0

這是技術細節。列表/向量或謂詞選擇是一個簡單的次要目標。 –

回答

3

對我而言,這裏直接的方法就夠了。請致電ShadowPrivateData遞歸地爲jsonValue的所有成員。在每個遞歸步驟中,您應該確定jsonValue是數組,對象還是都不是,並且正確地遍歷它。爲此,使用isArrayisObject

在迭代對象或數組的字段時,如果該字段不是聚合(對象或數組),請在listOfKeysWithPrivateData中搜索它的名稱。如果在列表中發現字段的名稱,確定字段的類型(使用isStringisDoubleisIntegral等),並與更換合適的領域:帶*號用零替換字符串,數字等

聲明listOfKeysWithPrivateDatastd::set<std::string>或類似的東西來執行對數搜索,而不是線性。

如何遍歷聚合對象?對象使用getMemberNames,陣列使用size。換句話說,jsoncpp爲json對象內省提供了一個完整的方法集合。

如果執行得當,這種方法應該審查所有敏感數據,而不要考慮它的複雜性。

0

所以我決定用@Sergey提議,並有這樣的事情:現在

// in header 
class CJSONUtils 
{ 
public: 
    static Json::Value HidePrivateData(const Json::Value& value, 
             const std::vector<std::string>& pathSufixes); 

private: 
    static void ShadowPrivateData(Json::Value& value, 
            const std::vector<std::string>& pathSufixes, 
            const std::string& sPath); 

    static bool IsPrivatePath(const std::string& sPath, 
           const std::vector<std::string>& pathSufixes); 

    static std::string MaskPrivateText(const std::string& sPrivateText); 
}; 

// in cpp 
#include "JSONUtils.h" 
#include "StringUtils.h" 
#include <algorithm> 
#include <json/json.h> 

using namespace std; 
using namespace Json; 

Value CJSONUtils::HidePrivateData(const Value& value, 
            const vector<string>& pathSufixes) 
{ 
    Value result { value }; 
    ShadowPrivateData(result, pathSufixes, {}); 
    return result; 
} 

void CJSONUtils::ShadowPrivateData(Value& value, 
            const vector<string>& pathSufixes, 
            const string& sPath) 
{ 
    switch (value.type()) 
    { 
     case nullValue: 
     case intValue: 
     case uintValue: 
     case realValue: 
     case booleanValue: 
      break; 

     case stringValue: 
      if (IsPrivatePath(sPath, pathSufixes)) 
      { 
       value = Value { MaskPrivateText(value.asString()) }; 
      } 
      break; 

     case arrayValue: 
      for (auto& arrayValue : value) 
      { 
       ShadowPrivateData(arrayValue, pathSufixes, sPath + "[]"); 
      } 
      break; 

     case objectValue: 
      for (auto it = value.begin(); it != value.end(); ++it) 
      { 
       ShadowPrivateData(*it, pathSufixes, sPath + "." + it.key().asString()); 
      } 
      break; 
    } 
} 

bool CJSONUtils::IsPrivatePath(const string& sPath, 
           const vector<string>& pathSufixes) 
{ 
    return std::any_of(pathSufixes.begin(), 
         pathSufixes.end(), 
         [&](const string& sSufix) 
         { 
          return EndsWith(sPath, sSufix); 
         }); 
} 

std::string CJSONUtils::MaskPrivateText(const std::string& sPrivateText) 
{ 
    if (sPrivateText.length() < 15) 
    { 
     return std::string(sPrivateText.length(), '*'); 
    } 
    ostringstream result; 
    result << "< *" << sPrivateText.length() << " characters * >"; 
    return result.str(); 
} 

因爲Json::Value重載流運算符這可以像這樣使用:

LOG() << " JSON received: " << CJSONUtils::HidePrivateData(jsonRoot, listOfPrivateItemsPaths); 

我已經寫了試驗它(gtest)和它的魅力。

相關問題