Search code examples
c++jsonnlohmann-json

How to delete nested json data using nlohmann c++


I have a below json data. I am using nlohmann json in C++.

{
    "CompanyName": "XYZ Tech",
    "Created": "2019-10-16T20:14:29Z",
    "TxnId": "4509237",
    "Tags": [
        {
            "ROIId": "Default",
            "Time": 71,
            "Tracker": "emp10"
        },
        {
            "ROIId": "MC16",
            "Time": 21,
            "TrackerId": "emp10"
        },
        {
            "ROIId": "Default",
            "Time": 11,
            "TrackerId": "emp11"
        },
        {
            "ROIId": "MC18",
            "Time": 10,
            "TrackerId": "emp11"
        }
    ],
    "Type": "TxnData"
}

In above json data, inside Tags, we have data where the ROIId is Default. I want to delete it so that the data becomes:

{
    "CompanyName": "XYZ Tech",
    "Created": "2019-10-16T20:14:29Z",
    "TxnId": "4509237",
    "Tags": [
        {
            "ROIId": "MC16",
            "Time": 21,
            "TrackerId": "emp10"
        },
        {
            "ROIId": "MC18",
            "Time": 10,
            "TrackerId": "emp11"
        }
    ],
    "Type": "TxnData"
}

How can I do it in c++. Thanks


Solution

  • I suggest iterating through the json::array stored in Tags and saving the Key of the matched elements. This way you can later validate the deletion and safely delete the elements.

    Note that deleting is exactly like erasing with a STL vector - I prefer to delete from the end of the vector to avoid changing the keys while deleting multiple elements.

    Here is a quick and dirty demo

    And here is the code:

    #include <iostream>
    #include <vector>
    #include "json3.6.1.hpp"
    
    unsigned removeDefaultROIID(nlohmann::json& jsonObject, const std::string& value) {
        std::vector<int> toremove;
        //Loop through the `tags` json::array and create a vector of indexes to delete:
        for (auto &it : jsonObject["Tags"].items()) {
        //`.get<std::string>()` is the best way to make sure we are getting the value as std::string
            if (it.value().at("ROIId").get<std::string>() == value) 
                toremove.push_back(stoi(it.key()));
        }
        //sort it before erase - we want to delete first biggest index:
        std::sort(toremove.rbegin(), toremove.rend());
        //delete using `.erase()` method:
        for (int &it : toremove)
            jsonObject["Tags"].erase(jsonObject["Tags"].begin() + it);
        return toremove.size();
    }
    
    int main()
    {
        //Create the JSON object:
        nlohmann::json jsonObject = R"({"CompanyName":"XYZ Tech","Created":"2019-10-16T20:14:29Z","TxnId":"4509237","Tags":[{"ROIId": "Default","Time": 71,"Tracker": "emp10"},{"ROIId":"MC16","Time": 21,"TrackerId": "emp10"},{"ROIId":"Default","Time":11,"TrackerId":"emp11"},{"ROIId":"MC18","Time": 10,"TrackerId":"emp11"}],"Type":"TxnData"})"_json;
    
        std::cout << "JSON nested object value conditional erase:" << std::endl;
        std::cout << "JSON object TAGS count - BEFORE deletion:" << jsonObject["Tags"].size() << std::endl;
        //Call the method -> jlson is passed by ref
        unsigned removed = removeDefaultROIID(jsonObject, "Default");
    
        std::cout << "JSON object TAGS count - AFTER deletion:" << jsonObject["Tags"].size() << std::endl;
    
        return 0;
    }