DEV Community

Cover image for Simple and easy-to-use JSON parser in C
Megabit
Megabit

Posted on

Simple and easy-to-use JSON parser in C

This article introduces the JSON parser of the open source C library Melon.

I believe many readers have heard of or even used the cJSON. So this article will compare cJSON and Melon’s JSON component.

Let’s take a look together below.

Encode

Suppose we want to build the following JSON:

{
    "name": "Awesome 4K",
    "resolutions": [
        {
            "width": 1280,
            "height": 720
        },
        {
            "width": 1920,
            "height": 1080
        },
        {
            "width": 3840,
            "height": 2160
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

So, let’s first take a look at the cJSON version:

#include <stdio.h>
#include <cjson/cJSON.h>

//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
    const unsigned int resolution_numbers[3][2] = {
        {1280, 720},
        {1920, 1080},
        {3840, 2160}
    };
    char *string = NULL;
    cJSON *resolutions = NULL;
    size_t index = 0;

    cJSON *monitor = cJSON_CreateObject();

    if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
    {
        goto end;
    }

    resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
    if (resolutions == NULL)
    {
        goto end;
    }

    for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
    {
        cJSON *resolution = cJSON_CreateObject();

        if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
        {
            goto end;
        }

        if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
        {
            goto end;
        }

        cJSON_AddItemToArray(resolutions, resolution);
    }

    string = cJSON_Print(monitor);
    if (string == NULL)
    {
        fprintf(stderr, "Failed to print monitor.\n");
    }

end:
    cJSON_Delete(monitor);
    return string;
}

int main(void)
{
    char *p;
    p = create_monitor_with_helpers();
    printf("%s\n", p);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Next, let’s take a look at the Melon’s:

#include <stdio.h>
#include "mln_json.h"
#include "mln_log.h"

static mln_string_t *generate(void)
{
    mln_json_t j;
    mln_string_t *ret;

    mln_json_init(&j);

    mln_json_generate(&j, "{s:s,s:[{s:d,s:d},{s:d,s:d},{s:d,s:d}]}", \
        "name", "Awesome 4K", "resolutions", "width", 1280, "height", 720, \
        "width", 1920, "height", 1080, "width", 3840, "height", 2160);
    ret = mln_json_encode(&j);

    mln_json_destroy(&j);

    return ret;
}

int main(void)
{
    mln_string_t *p;
    p = generate();
    mln_log(none, "%S\n", p);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Decode

We have the following JSON:

{
    "name": "Awesome 4K",
    "resolutions": [
        {
            "width": 1280,
            "height": 720
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Let's take a look at the decoding, cJSON first:

#include <stdio.h>
#include <cjson/cJSON.h>

int supports_full_hd(const char * const monitor)
{
    const cJSON *resolution = NULL;
    const cJSON *resolutions = NULL;
    cJSON *monitor_json = cJSON_Parse(monitor);
    if (monitor_json == NULL)
        return -1;

    resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
    cJSON_ArrayForEach(resolution, resolutions)
    {
        cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
        return width->valuedouble;
    }

    cJSON_Delete(monitor_json);
    return -1;
}

int main(void)
{
    char p[] = "{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720}]}";
    int i = supports_full_hd(p);
    printf("%d\n", i);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Next is the Melon's:

#include <stdio.h>
#include "mln_json.h"
#include "mln_log.h"

static int handler(mln_json_t *j, void *data)
{
    return (int)mln_json_number_data_get(j);
}

static int parse(mln_string_t *p)
{
    mln_json_t j;
    mln_string_t exp = mln_string("resolutions.0.width");
    mln_json_decode(p, &j);
    return mln_json_parse(&j, &exp, handler, NULL);
}

int main(void)
{
    mln_string_t p = mln_string("{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720}]}");
    int i = parse(&p);
    mln_log(none, "%d\n", i);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Write at the end

Melon's JSON component mainly provides the following four functions to facilitate users to encode and decode JSON:

  • mln_json_decode decodes JSON strings into JSON structure nodes
  • mln_json_parse obtains the corresponding JSON sub-node from the decoded JSON structure based on the given expression
  • mln_json_generate builds a JSON structure based on the given format information
  • mln_json_encode generates a JSON string based on the generated JSON structure

Melon's JSON component provides a functional interface that is easy to read and use, making it easier for developers to maintain projects.

Welcome to try the open source C library Melon.

Github:https://github.com/Water-Melon/Melon

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay