jsmn: A Powerful C Library for JSON Parsing

jsmn is a minimalistic and high-performance JSON parser written in C, particularly suitable for use in resource-constrained embedded environments. Its design goal is to maintain a very small code size and memory footprint while not relying on any external libraries.

The table below summarizes the main features of jsmn for quick reference:

Feature Category Details
Code and Dependencies Approximately 200 lines of code, with no library dependencies (not even libc), highly portable
Memory and Performance No dynamic memory allocation, fast parsing speed, minimal memory overhead
API Design Extremely simple API, with only two main functions
Compatibility Compatible with C89, high code portability

🛠️ Installation and Project Integration

Getting the Source Code

The source code for jsmn is hosted on GitHub, and you can clone the repository directly:

git clone https://github.com/zserge/jsmn.git

Compilation and Integration

Compiling jsmn is very straightforward. After entering the source directory, you can compile it using the make command. The project directory mainly contains the following files:

  • jsmn.c: The main implementation file of the library.
  • jsmn.h: Contains function declarations and necessary macro definitions.
  • demo.c: Example code demonstrating basic usage.

To integrate jsmn into your project, you typically only need to:

  1. Add #include "jsmn.h" in your source code.
  2. Compile and link jsmn.c during the build, for example:
  3. gcc -o your_program your_program.c jsmn/jsmn.c -Ijsmn

💻 Core Usage and Code Example

When jsmn parses JSON, it breaks the string into a series of tokens. Each token corresponds to a data segment in the JSON, recording its starting position, ending position, and type in the string.

Basic Usage Flow

The following example demonstrates the basic steps for using jsmn to parse JSON:

#include <stdio.h>
#include <string.h>
#include "jsmn.h" // Include jsmn header file

// A helper function to compare the content of tokens in the JSON string with a given string
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
    if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start &&
        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
        return 0;
    }
    return -1;
}

int main() {
    // 1. Define the JSON string to be parsed
    const char *json_string = "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000}";

    jsmn_parser p;      // Declare parser object
    jsmntok_t t[128];   // Pre-allocate a token array (token pool)

    jsmn_init(&p); // Initialize parser

    // 2. Execute parsing
    int num_tokens = jsmn_parse(&p, json_string, strlen(json_string), t, sizeof(t)/sizeof(t[0]));

    if (num_tokens < 0) {
        printf("Parsing failed, error code: %d\n", num_tokens);
        return 1;
    }

    // 3. Loop through all tokens to extract needed data
    for (int i = 1; i < num_tokens; i++) { 
        if (jsoneq(json_string, &t[i], "user") == 0) {
            // Use the position information in the token to directly print the segment from the original JSON string
            printf("- user: %.*s\n", t[i+1].end - t[i+1].start, json_string + t[i+1].start);
            i++; // Skip the next token, as it is the value of the current key
        } else if (jsoneq(json_string, &t[i], "uid") == 0) {
            printf("- UID: %.*s\n", t[i+1].end - t[i+1].start, json_string + t[i+1].start);
            i++;
        }
    }

    return 0;
}

💡 Advanced Applications and Considerations

  • Handling Large JSON Data: For large JSON data, you can adjust the size of the token pool to ensure there is enough space to accommodate all tokens.
  • Configuring Compilation Options: jsmn provides several compilation options, such as JSMN_STRICT for enabling stricter JSON syntax checks, which can be defined at compile time using the -D flag.

🔄 Comparison with Other Libraries

jsmn and cJSON are both commonly used JSON parsing libraries in C, but they differ in their positioning and implementation:

Feature jsmn cJSON
Design Philosophy Minimalism, only performs token parsing Feature-rich, builds a complete DOM tree
Memory Management No dynamic memory allocation, user must pre-allocate token pool Uses dynamic memory allocation, must be manually freed
Code Size Extremely small code footprint Relatively larger
Use Cases Extremely resource-constrained embedded systems Relatively resource-rich scenarios requiring convenient operations

In simple terms, jsmn provides you with raw materials (tokens) that you need to process yourself; whereas cJSON provides pre-processed parts. When choosing, if your system resources are very tight and primarily focused on JSON parsing rather than construction, jsmn is the better choice.

Leave a Comment