Need Help: Best way to work with JSON API responses in C

#1

Hey all,

I’m trying to fetch weather data using the DarkSky API, and I’m looking for some advice on the best way to work with JSON in Mongoose OS.

  1. How to call the API and get the response
  • I’ve found an example that achieves this using mg_connect_http() and writing the http chunks as they come in to file.
  • I’m looking for an example of this could be done in memory
  1. Once I’ve received the response I need to extract a few specific bits of info from the response. A typical API response is something like this:

}

{
          "latitude": 42.3601,
          "longitude": -71.0589,
          "timezone": "America/New_York",
          "currently": {
              "time": 1509993277,
              "summary": "Drizzle",
              "uvIndex": 1,
              "visibility": 9.84,
              "ozone": 267.44
          }
}

As an example I’d like to be able to extract the “timezone” and the “summary” information nested under “currently”.

I’ve been looking at the frozen library but have had zero luck getting anything working.
Any suggestions/ideas/links/tips would be much appreciated.

Thanks.

1 Like
#2

frozen is your friend:

  char *summary = NULL;
  char *timezone = NULL;
  json_scanf(json, json_len, "{timezone: %Q, currently: {summary: %Q}}",
             &timezone, &summary);
  LOG(LL_INFO, ("timezone: %s, summary: %s", timezone, summary));
  free(timezone);
  free(summary);
1 Like
#4

I looked at how we’re pulling info from our RPCs with nested information – it’s exactly the same as what nliviu has posted, so I’d only wind up writing the same thing. :slight_smile: But, it works for us!

#5

Thanks for the suggestion @nliviu! I’ve definitely got something similar in other parts of my code around RPC callbacks, not sure why I was over-complicating things.

This method was working great till I realised I wanted something from within an array from the response, the JSON response looks like:

{
  "currently":
    {
      "time": 1582803248,
      "temperature": 16.68,
      "humidity": 0.68,
      "cloudCover": 0.43,
    },
  "daily":
    {
      "summary": "Possible light rain on Monday through next Thursday.",
      "icon": "rain",
      "data":
        [
          {
            "time": 1582722000,
            "summary": "Clear throughout the day.",
            "icon": "clear-day",
            "temperatureHigh": 20.7,
            "temperatureHighTime": 1582779360,
            "temperatureLow": 13.5,
            "temperatureLowTime": 1582836480,
            "apparentTemperatureHigh": 20.42,
            "apparentTemperatureHighTime": 1582779360,
            "apparentTemperatureLow": 13.77,
            "apparentTemperatureLowTime": 1582836480,
          },
          {
            "time": 1582808400,
            "summary": "Overcast throughout the day.",
            "icon": "cloudy",
            "temperatureHigh": 20.54,
            "temperatureHighTime": 1582867380,
            "temperatureLow": 10.63,
            "temperatureLowTime": 1582919820,
            "apparentTemperatureHigh": 20.26,
            "apparentTemperatureHighTime": 1582867380,
            "apparentTemperatureLow": 10.9,
            "apparentTemperatureLowTime": 1582919820,
          },
        ],
    },
  "offset": 11,
}

I was trying to extract the entire array like I saw here but its not working. The example has the array one layer deep, but mine is two layers deep. Not exactly sure how to use the “.” formatting to represent that.

I’ve tried a few different ways with no luck, but basically my code looks like this:

struct json_token t;
float value;

for (int i = 0; json_scanf_array_elem(response, strlen(response), ".data", i, &t) > 0; i++) {
  json_scanf(t.ptr, t.len, "{temperatureLow: %f}", &value);
  LOG(LL_INFO, ("value: %f", value));
}
1 Like
#6

This works:

  struct json_token t;
  float value;
  for (int i = 0;
       json_scanf_array_elem(json, json_len, ".daily.data", i, &t) > 0; i++) {
    json_scanf(t.ptr, t.len, "{temperatureLow: %f}", &value);
    LOG(LL_INFO, ("value: %f", value));
  }
1 Like
#7

Once again, thanks @nliviu! Worked like a charm :smile: