Search code examples
c++visual-c++

Write complex nested json using nlohmann


We want to write JSON output by reading different inputs. Here is a sample output JSON format. The "FeatureDetails" records will be increasing depending on the input. Please guide me on how to write the desired output. I checked the user forum, but it mostly explained parsing rather than writing.

{
    "LayerData": [
    {
      "FeatureName": "Network",
      "GeometryType": "Line",      
      "FeatureDetails": [
        {
          "FeatureID": 7,          
          "Area": 0.0,          
          "FromDat": [
            "Network:7",
            "Network:244",
            "Points:709"
          ],
          "EndPoint": "638493.493137151,4561653.29740454",
          "ToDat": [
            "Network:7",
            "ticks:125",
            "ticks:126"
          ]
        },
        {
          "FeatureID": 83,          
          "Area": 0.0,          
          "FromDat": [
            "Network:83",
            "Network:84",
            "Points:369"
          ],
          "EndPoint": "638430.41,4562051.04",
          "ToDat": [
            "Network:83",
            "Network:319",
            "Points:364"
          ]
        },
        {
          "FeatureID": 84,          
          "Area": 0.0,          
          "FromDat": [
            "Network:84",
            "Network:318",
            "ticks:34",
            "CPoint:38",
            "Points:365"
          ],
          "EndPoint": "638468.91,4562021.03",
          "ToDat": [
            "Network:83",
            "Network:84",
            "Points:369"
          ]
        }       
        ]
    }
  ]
}

so far I tried this but didn't get desired output.

std::ofstream jsonOut(jsonOutputPath);

js["LayerData"]["GeometryType"] = "Line";
js["LayerData"]["FeatureName"] = strLayerName;

while (Cursor->NextFeature(&feature) == S_OK)
{
    js["LayerData"]["FeatureDetails"]["FeatureID"] = ID;
        js["LayerData"]["FeatureDetails"]["Area"] = area;

    js["LayerData"]["FeatureDetails"]["FromDat"] = fromArr;
        js["LayerData"]["FeatureDetails"]["ToDat"] = toArr;

    jsonOut << std::setw(4) << js;
}

Solution

  • You can construct the outer shell in a single call to the json constructor. The initializer list form is smart enough to figure out whether you want to construct an object or an array.

    json doc{
        {"LayerData",
            json::array({
                json{
                    { "FeatureName", "Network" },
                    { "GeometryType", "Line" },
                    { "FeatureDetails", json::array() },
                }})
        }
    };
    

    You can then grab the FeatureDetails array and call push_back to add extra objects:

    json& featureDetails = doc["LayerData"][0]["FeatureDetails"];
    
    while (Cursor->NextFeature(&feature) == S_OK) {
        json detail{
            { "FeatureId", ID },
            { "Area", Area },
            { "FromDat", fromArr },
            { "ToDat", toArr },
        };
        featureDetails.push_back(detail);
    }