我想分析一個類似於JSON的文本文件。經過一些字符轉換後,它仍然有一些對象,這些對象存在關鍵衝突。所以,我的JSON是這樣的:cpp RapidJSON - 解決沒有信息丟失的密鑰衝突
{
"key1": {
"a": "asdf",
"a": "foo",
"a": "bar",
"a": "fdas"
}
}
,我想它解析成這樣:
{
"key1": {
"a": [
"asdf",
"foo",
"bar",
"fdas"
]
}
}
我試着用JsonCpp來實現這一點,但它不能處理的主要衝突。所以我選擇使用RapidJSON,尤其是因爲它可以在解析時保留所有的關鍵衝突成員。
然後,爲了解決無信息丟失的關鍵矛盾,我寫了下面的遞歸RapidJSON cpp的代碼:
void resolveKeyConflicts(rj::Value& value) {
if (value.IsObject()) {
std::map<std::string, unsigned int> nameCount;
for (rj::Value::MemberIterator vMIt = value.MemberBegin();
vMIt != value.MemberEnd(); vMIt++) {
std::string name(vMIt->name.GetString());
if (nameCount.find(name) == nameCount.end()) {
nameCount[name] = 1;
} else {
nameCount[name] += 1;
}
}
for (std::map<std::string, unsigned int>::iterator nCIt =
nameCount.begin(); nCIt != nameCount.end(); nCIt++) {
if (nCIt->second > 1) {
rj::Value newArray(rj::kArrayType);
for (rj::Value::MemberIterator vFMIt = value.FindMember(
nCIt->first.c_str()); vFMIt != value.MemberEnd();
vFMIt++) {
if (vFMIt->name.GetString() == nCIt->first) {
rj::Value value(vFMIt->value, this->GetAllocator());
newArray.PushBack(value, this->GetAllocator());
}
}
value.EraseMember(value.FindMember(nCIt->first.c_str()),
value.MemberEnd());
rj::Value key(nCIt->first.c_str(), nCIt->first.length(),
this->GetAllocator());
value.AddMember(key, newArray, this->GetAllocator());
}
}
for (rj::Value::MemberIterator vMIt = value.MemberBegin();
vMIt != value.MemberEnd(); vMIt++) {
if (vMIt->value.IsObject() || vMIt->value.IsArray()) {
resolveKeyConflicts(vMIt->value);
}
}
} else if (value.IsArray()) {
for (rj::Value::ValueIterator vVIt = value.Begin(); vVIt != value.End();
vVIt++) {
resolveKeyConflicts(*vVIt);
}
}
}
這工作不錯,只要衝突的關鍵成員是該對象的唯一成員。這可以,我想,可以用簡單的代碼存檔,但我還試圖能夠解決這樣的任意鍵衝突:
{
"key2": {
"a": "asdf",
"b": "foo",
"b": "bar",
"c": "fdas"
}
}
進入這個:
{
"key2": {
"a": "asdf",
"b": [
"foo",
"bar"
],
"c": "fdas"
}
}
原來FindMember
不,正如我所想的那樣,使用相同的密鑰名稱爲所有成員提供一個迭代器,但只是使用該密鑰的第一個成員的位置。我認爲我的python思維方式可能與我對FindMember
的期望相矛盾。所以像這樣,代碼將會失去"c": "fdas"
成員。
我依靠MemberIterator EraseMember(MemberIterator first, MemberIterator last)
,因爲刪除http://rapidjson.org/md_doc_tutorial.html#ModifyObject中提到的成員的所有其他方法在刪除key1
情況下的最後一個成員似乎都有問題。但EraseMember
這樣的情況絕對是key2
的錯誤選擇。
所以我有點迷失在這裏。可以請有人指出我正確的方向來解決沒有信息丟失的關鍵衝突,它可以處理key1
和key2
案件?
編輯:我使用https://github.com/miloyip/rapidjson/tree/v1.0.2的RapidJSON,位於v1.0.2
標記處。
重複的鍵不是有效的JSON。 –
@DavidHammen在ECMA-404中,「對象結構表示爲一對圍繞着零個或多個名稱/值對的大括號標記 名稱是一個字符串,一個單獨的冒號令牌跟隨每個名稱,將名稱與值。一個逗號記號將一個值與下一個名稱分開。「重複名稱沒有限制。 –
@DavidHammen在RFC 7159中,「對象內的名稱應該是唯一的」。這不是必須的。一些程序能夠處理它們,但有些可能不能。 –