How to decode json data from google api

415 Views Asked by At

I'm using below code in my program to get the latitude and longitude.

system("curl -d @gateway_req.json -H \"Content-Type: application/json\" -i \"https://www.googleapis.com/geolocation/v1/geolocate?key=MY_API_KEY");

This returns as below,

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: X-Origin
Vary: Referer
Date: Fri, 04 Sep 2020 16:15:39 GMT
Server: scaffolding on HTTPServer2
Cache-Control: private
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Alt-Svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=25                                                                                                             92000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2                                                                                                             592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Accept-Ranges: none
Vary: Origin,Accept-Encoding
Transfer-Encoding: chunked

{
  "location": {
    "lat": 20.7732224,
    "lng": -13.990144
  },
  "accuracy": 1030
}

I want to decode lat and lng value separately and store it in an array.

I've jansson lib installed but not sure how to use it. Can you please give me some idea how to do this?

1

There are 1 best solutions below

1
On BEST ANSWER

First you need to find the start of the payload. This is after an empty line was found.

Then you need to parse the string via json_loads and you receive a root JSON object. The data you are looking for is stored in an embedded object "location" which you can retrieve via json_object_get. Then you can parse the content. This can be done in 2 ways:

  • You can use a format string to parse members of that object or
  • You can get the child objects of the location object and retrieve the value of each.

After your work is done you need to decrement the reference counter to allow freeing of the objects.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jansson.h>


// gcc -o json-test `pkg-config --cflags jansson` json.c `pkg-config --libs jansson`

int main(void)
{
    FILE *input = fopen("curl-data.txt","rt");
    if (input == NULL) {
        fprintf(stderr, "Cannot open curl-data.txt.\n");
        return 1;
    }
      
    // sample data has 878 bytes. 
    char buffer[1024];
    int num = fread(buffer, 1, sizeof(buffer)-1, input);
    buffer[num]=0;
    
// In this example the payload format is known and we can directly search
// for the start. In HTTP packets header and payload are separated by an empty 
// line and that can be used to search for start of payload.

    char *data_start = strstr(buffer, "{");
    if (data_start == NULL) {
        fprintf(stderr, "did not find start of payload.\n");
        return 1;
    }
    printf("Payload: ###\n%s\n###\n", data_start);
    
    json_error_t err;
    json_t *root = json_loads(data_start, 0, &err);
    if (root == NULL) {
        fprintf(stderr, "Failed to parse input string: %s\n", err.text);
        return 1;
    }

    if (!json_is_object(root)) {
        fprintf(stderr, "root is not an object\n");
        json_decref(root);
        return 1;
    }
    
    json_t *location = json_object_get(root, "location");
    if (location == NULL || !json_is_object(location)) {
        fprintf(stderr, "Location element not found or not an object\n");
        json_decref(root);
        return 1;
    }

    double lat, lng;

// alternative 1:
    int res = json_unpack(location, "{s:f, s:f}", "lat", &lat, "lng", &lng);
    if (res != 0) {
        fprintf(stderr, "lat/lng elements not found\n");
        json_decref(root);
        return 1;
    }
    printf("1) lat: %f; lng: %f\n", lat, lng);

// alternative 2:
    json_t *latval = json_object_get(location, "lat");
    if (latval == NULL || !json_is_real(latval)) {
        fprintf(stderr, "lat element not found or not a number\n");
        json_decref(root);
        return 1;
    }
    json_t *lngval = json_object_get(location, "lng");
    if (lngval == NULL || !json_is_real(lngval)) {
        fprintf(stderr, "lng element not found or not a number\n");
        json_decref(root);
        return 1;
    }
    
    lat = json_number_value(latval);
    lng = json_number_value(lngval);

    printf("2) lat: %f; lng: %f\n", lat, lng);

    json_decref(root);

    return 0;
}

I would need to dig into the manual whether you also need to decrement refcounter for the other 2 objets as well.