How to Use Json-cpp for Efficient JSON String Parsing in C++

Posted by Riino on

Use Json-cpp to Parse JSON String

Environment : Json-cpp , C++

1. Foreword

Keep it in mind that the judge point may located in the assert processing , that any error when parsing can trigger a assert error , which will kill the program.

2. First Step

Establish objects for Reader and Value.

Json::Reader *pJsonParser = new Json::Reader(Json::Features::strictMode()); //If you want to switch on strict mode.
Json::Reader reader;
Json::Value value;

Note: Strict mode can be used to parse unknow json , like a array out of a "[]". In a case this may trigger 'Assert Failed'.

3. Second Step

3.1. Start Parsing.

Analyze the structure of your json string. I recommend some tools online that you can find easily in internet to color json string. In the view of Json-cpp , '1' and 1 is totally two different things.

There should be several layers in a json string , each one contains 2 format of its member : element and array .

Here is a simple example , The outermost element of this Json string is date , message,status,cityandcount, and it has a sub-layer called data, which contains humidity,pm25,pm10,qualityandTem. To show it clearly , I put indentation for each layer :

{
  "date": "20180828",
  "message": "Success !",
  "status": 200,
  "city": "Chongqing",
  "count": 19,
  "data": {
    "humidity": "52%",
    "pm25": 44,
    "pm10": 77,
    "quality": "low polution",
    "temp": "30"
  }
}

Be aware of the different between 20180828 and 200.

I wrote two struct to save the information in these elements, which create objects called json and data.

Be aware of the type asXXXX function in the end , which decide the type of returned data value["XXXX"]. It must be exactly same with the type of the data of json string , and the type of the data defined in struct we write. Of course , the type of string can be defined as String or CString freely.

if (reader.parse(obj.GetCityWeatherJson(), value))
  {
       Json.date = value["date"].asCString();
       Json.message = value["message"].asCString();
       Json.status = value["status"].asInt();
       Json.city = value["city"].asCString();
       Json.count = value["count"].asInt();
           const Json::Value arrayObj = value["data"];
           data.shidu = arrayObj["shidu"].asCString();
           data.pm25 = arrayObj["pm25"].asInt();
           data.pm10 = arrayObj["pm10"].asInt();
           data.quality = arrayObj["quality"].asCString();
           data.wendu = arrayObj["wendu"].asCString();
           data.ganmao = arrayObj["ganmao"].asCString();
  }

3.2. Parsing an Array.

For example , there's a array in a layer , and each element in the array has same type of data . Check this json:

"forecast": [
    {
       "date": "28th,Sat.",
       "sunrise": "06:28",
       "high": " 37.0℃",
       "low": " 28.0℃",
       "sunset": "19:22",
       "aqi": 51,
       "type": "Cloudy",

    },
    {
       "date": "01st,Sat",
       "sunrise": "06:30",
       "high": "35.0℃",
       "low": "27.0℃",
       "sunset": "19:17",
       "aqi": 42,
       "type": "Cloudy",
    }
  ]

Now we need to declare a vector like :

std::vector<ST_forecast>ForecastList;

And declare corresponding struct : ST_data , ForecastList is the name of our container.

Here is the parsing code:

const Json::Value subArrayObj2 = arrayObj["forecast"];
for (unsigned int i = 0; i < subArrayObj2.size(); ++i)
{
forecast.date = subArrayObj2[i]["date"].asCString();
forecast.sunrise = subArrayObj2[i]["sunrise"].asCString();
forecast.high = subArrayObj2[i]["high"].asCString();
forecast.low = subArrayObj2[i]["low"].asCString();
forecast.sunset = subArrayObj2[i]["sunset"].asCString();
forecast.aqi = subArrayObj2[i]["high"].asInt();
forecast.type = subArrayObj2[i]["type"].asCString();
data.ForecastList.push_back(forecast);
}

How it works ?

First we need a function size to give us a number to show how many element this array have , then establish the object subArrayObj2[i] , in each process , put the data in forecast , and use function pushback to push it into the vector.

If you don know exactly how vector and pushback work , you need just understand you can use data.ForecastList[i].XXX to call the data called xxxin No. i element by doing this. For example , the data in data.ForecastList[0].date will be "28th, Sat." , and data.ForecastList[1.date is "01st, Sat." .