Parsing JSON in C wasn’t so easy until I comparing several libraries, but trying JSON-C was easier than I think. let talk about sample case which I want to parse json data from http request, so I use curl for processing my requests and using JSON-C to parse the data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <json-c/json.h>
like usually started with including headers, then beginning to write the code that handle requests to our endpoint
int main() {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://fabianoo.net/endpoint/");
#ifdef SKIP_PEER_VERIFICATION
/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#ifdef SKIP_HOSTNAME_VERIFICATION
/*
* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
this would return the output directly to streams which we couldn’t process the data , but this can be done with this method.
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s) {
s->len = 0;
s->ptr = malloc(s->len + 1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) {
size_t new_len = s->len + size * nmemb;
s->ptr = realloc(s->ptr, new_len + 1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr + s->len, ptr, size * nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size * nmemb;
}
and then add these lines to our main block
struct string s;
init_string(&s);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
// Then we could confirming to streams with this line
printf("response: %s\n", s.ptr);
okay so we’re done with the requests and our json could be like this
[
{
"id": "117",
"name": "Reyhan Fabiano",
"description": "HikiProgrammer"
}
]
before going further, I’ll explain what happened in the curl output directed to streams, like I said that we should enter several lines to make this possible, curl wasn’t handle the response until we do something which mean we should set option that they must do something when data appear and where do they store and it’s the setopt method.
so, back to the business where we only need to parse the json data from response string and get started to import the json-c libraries.
#include <json-c/json.h>
then we declare the initial variable container
struct json_object *parsed_json;
struct json_object *data;
struct json_object *id;
struct json_object *name;
struct json_object *description;
so what we only need after whis just parser method
parsed_json = json_tokener_parse(s.ptr);
json_object_object_get_ex(data, "id", &id);
json_object_object_get_ex(data, "name", &name);
json_object_object_get_ex(data, "description", &description);
// Confiriming the output with this line
printf("ID: %s\nName: %s\nDescription: %s",
json_object_get_string(id)
json_object_get_string(name)
json_object_get_string(pos)
);
based on my references, that should be parsed but actually that not the real problems, my case were nested inside an array so we could add something like this to select index from array.
data = json_object_array_get_idx(parsed_json, 0);
and that should be done the work and expected output were
ID: 117
Name: Reyhan Fabiano
Deskripsi: HikiProgrammer
many people also ask me the best way to compile it and what I used it mostly was clang and these the compile option I used to this code
clang -Wall -g -I/usr/local/include/json-c -I/usr/include/x86_64-linux-gnu/curl -o corona corona.c -ljson-c -lcurl
References: