I am working in C language, visual studio 2022, and using jsoncpp library for working with Json.
To Give you an Idea, here is an example of Json data I am working with
[
{
"name":"Regina Eagle",
"job":"Biologist",
"salary":"728148120",
"email":"[email protected]",
"city":"Nashville"
},
{
"name":"Julius Baker",
"job":"Fabricator",
"salary":"299380360",
"email":"[email protected]",
"city":"Las Vegas"
},
{
"name":"Rocco Sawyer",
"job":"Chef Manager",
"salary":"223764496",
"email":"[email protected]",
"city":"San Francisco"
},
{
"name":"Chad Murray",
"job":"Project Manager",
"salary":"43031808",
"email":"[email protected]",
"city":"Bridgeport"
},
{
"name":"Rocco Parker",
"job":"Lecturer",
"salary":"322089172",
"email":"[email protected]",
"city":"Indianapolis"
}
]
It's a Json array of objects (with key:value pairs). I have a set of column heads for eg: {"name","job","salary"}, and I want to sort the json data in a way that each object will have only columns that are in the given set.
This is my approach:
Store json data in a Json::Value object (let us say records).
Iterate through records (as it is an array).
Creating another loop to Iterate through object stored at each index.
Extract the key of the key:value pair and check if it's present in the set or not.
If it's present then continue, else if it isn't then remove that key:value entry from there.
This way we can delete unwanted column while looping through the object.
Here, is the code snippet:
set<string> col {"name","job","salary"};
Json::Value records = [
{
"name":"Regina Eagle",
"job":"Biologist",
"salary":"728148120",
"email":"[email protected]",
"city":"Nashville"
},
{
"name":"Julius Baker",
"job":"Fabricator",
"salary":"299380360",
"email":"[email protected]",
"city":"Las Vegas"
},
{
"name":"Rocco Sawyer",
"job":"Chef Manager",
"salary":"223764496",
"email":"[email protected]",
"city":"San Francisco"
},
{
"name":"Chad Murray",
"job":"Project Manager",
"salary":"43031808",
"email":"[email protected]",
"city":"Bridgeport"
},
{
"name":"Rocco Parker",
"job":"Lecturer",
"salary":"322089172",
"email":"[email protected]",
"city":"Indianapolis"
}
];
for (int i = 0; i<records.size(); i )
{
for (auto j = records[i].begin(); j != records[i].end(); j )
{
string key = j.key().asString();
if (col.find(key) != col.end())
{
continue;
}
else
{
records[i].removeMember(key);
}
}
}
It works fine until the 'removeMember' function get to run, and throws an error saying can't increament the value of iterator.
Expression: cannot increment value-initialized map/set iterator
Am I doing something wrong?
Or there is another/better way of doing this ?
Please advice.
CodePudding user response:
Don't remove or add elements in a container you're currently iterating.
The JSON objects are stored in a std::map
and removeMember
calls std::map::erase
. It invalidates the current iterator and it can't be incremented anymore. j
causes the error.
One approach is to first only store the keys of properties you want to delete, and then to delete the properties in a separate loop.
set<string> col {"name","job","salary"};
Json::Value records = [
{
"name":"Regina Eagle",
"job":"Biologist",
"salary":"728148120",
"email":"[email protected]",
"city":"Nashville"
},
{
"name":"Julius Baker",
"job":"Fabricator",
"salary":"299380360",
"email":"[email protected]",
"city":"Las Vegas"
},
{
"name":"Rocco Sawyer",
"job":"Chef Manager",
"salary":"223764496",
"email":"[email protected]",
"city":"San Francisco"
},
{
"name":"Chad Murray",
"job":"Project Manager",
"salary":"43031808",
"email":"[email protected]",
"city":"Bridgeport"
},
{
"name":"Rocco Parker",
"job":"Lecturer",
"salary":"322089172",
"email":"[email protected]",
"city":"Indianapolis"
}
];
for (int i = 0; i<records.size(); i )
{
std::vector<std::string> toRemove;
for (auto j = records[i].begin(); j != records[i].end(); j )
{
string key = j.key().asString();
if (col.find(key) != col.end())
{
continue;
}
else
{
// records[i].removeMember(key);
toRemove.push_back(key);
}
}
for (const auto &key : toRemove)
{
records[i].removeMember(key);
}
}