RapidJSON

libraryserializationJSONC++high-performance

Library

RapidJSON

Overview

RapidJSON is a fast JSON parser/generator library for C++ with both SAX/DOM style API. It achieves extremely high performance with minimal memory footprint. As a header-only library with no external dependencies, it's very easy to integrate into projects.

Details

RapidJSON is designed for extremely fast JSON processing, as its name suggests. With SIMD (Single Instruction, Multiple Data) instruction set support, it leverages processor features like SSE2, SSE4.2, and ARM Neon to maximize performance.

Key features:

  • High Performance: Industry-leading performance, outperforming many other JSON libraries in benchmarks
  • Memory Efficiency: Minimal memory allocation, with in-situ parsing to further reduce memory usage
  • Full JSON Compliance: Fully compliant with RFC 7159, supporting UTF-8, UTF-16, and UTF-32 encodings
  • Flexible APIs: Provides both DOM API for ease of use and SAX API for advanced control
  • Error Handling: Detailed error information and error position reporting
  • JSON Pointer: RFC 6901 compliant JSON Pointer for efficient data access
  • Schema Validation: Data validation capabilities with JSON Schema

Pros and Cons

Pros

  • Industry-Leading Performance: Records fastest processing speeds in many benchmarks
  • Header-Only: Simple project integration without complex build configurations
  • No External Dependencies: Works standalone without depending on other libraries
  • Comprehensive Features: Complete feature set including DOM/SAX APIs, JSON Pointer, schema validation
  • Platform Independent: Works on Windows, Linux, macOS, and various embedded systems
  • Extensive Documentation: Rich documentation and sample code
  • Active Development: Maintained by Tencent with continuous improvements

Cons

  • C++11 Required: Cannot be used with older compilers (minimum GCC 4.7.3, Clang 3.3, MSVC 2013)
  • JSON Only: Doesn't support other formats like XML or YAML
  • Learning Curve: Advanced features (SAX API, custom allocators) require time to master
  • Compile Time: As a header-only library, may increase compile times in large projects

References

Code Examples

Basic JSON Parsing (DOM API)

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>

using namespace rapidjson;

int main() {
    // 1. Parse a JSON string into DOM
    const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
    Document d;
    d.Parse(json);

    // 2. Modify it by DOM
    Value& s = d["stars"];
    s.SetInt(s.GetInt() + 1);

    // 3. Stringify the DOM
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    d.Accept(writer);

    // Output: {"project":"rapidjson","stars":11}
    std::cout << buffer.GetString() << std::endl;
    return 0;
}

Creating JSON Objects and Arrays

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

int main() {
    Document d;
    d.SetObject();
    Document::AllocatorType& allocator = d.GetAllocator();

    // Add string
    d.AddMember("name", "RapidJSON", allocator);
    
    // Add number
    d.AddMember("version", 1.1, allocator);
    
    // Create and add array
    Value features(kArrayType);
    features.PushBack("fast", allocator);
    features.PushBack("efficient", allocator);
    features.PushBack("header-only", allocator);
    d.AddMember("features", features, allocator);

    // Convert to JSON string
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    d.Accept(writer);
    
    std::cout << buffer.GetString() << std::endl;
    return 0;
}

Efficient Parsing with SAX API

#include "rapidjson/reader.h"
#include <iostream>

using namespace rapidjson;

// SAX Handler implementation
struct MyHandler : public BaseReaderHandler<UTF8<>, MyHandler> {
    bool Null() { std::cout << "Null()" << std::endl; return true; }
    bool Bool(bool b) { std::cout << "Bool(" << std::boolalpha << b << ")" << std::endl; return true; }
    bool Int(int i) { std::cout << "Int(" << i << ")" << std::endl; return true; }
    bool Uint(unsigned u) { std::cout << "Uint(" << u << ")" << std::endl; return true; }
    bool Int64(int64_t i) { std::cout << "Int64(" << i << ")" << std::endl; return true; }
    bool Uint64(uint64_t u) { std::cout << "Uint64(" << u << ")" << std::endl; return true; }
    bool Double(double d) { std::cout << "Double(" << d << ")" << std::endl; return true; }
    bool String(const char* str, SizeType length, bool copy) { 
        std::cout << "String(" << str << ", " << length << ", " << std::boolalpha << copy << ")" << std::endl;
        return true;
    }
    bool StartObject() { std::cout << "StartObject()" << std::endl; return true; }
    bool Key(const char* str, SizeType length, bool copy) { 
        std::cout << "Key(" << str << ", " << length << ", " << std::boolalpha << copy << ")" << std::endl;
        return true;
    }
    bool EndObject(SizeType memberCount) { std::cout << "EndObject(" << memberCount << ")" << std::endl; return true; }
    bool StartArray() { std::cout << "StartArray()" << std::endl; return true; }
    bool EndArray(SizeType elementCount) { std::cout << "EndArray(" << elementCount << ")" << std::endl; return true; }
};

int main() {
    const char* json = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}";

    MyHandler handler;
    Reader reader;
    StringStream ss(json);
    reader.Parse(ss, handler);

    return 0;
}

Reading JSON from File

#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include <cstdio>

using namespace rapidjson;

int main() {
    FILE* fp = fopen("config.json", "r");
    if (!fp) {
        std::cerr << "Failed to open file" << std::endl;
        return 1;
    }

    char readBuffer[65536];
    FileReadStream is(fp, readBuffer, sizeof(readBuffer));

    Document d;
    d.ParseStream(is);
    fclose(fp);

    // Access JSON data
    if (d.HasMember("database")) {
        const Value& db = d["database"];
        if (db.HasMember("host") && db["host"].IsString()) {
            std::cout << "Database host: " << db["host"].GetString() << std::endl;
        }
    }

    return 0;
}

Error Handling

#include "rapidjson/document.h"
#include "rapidjson/error/en.h"

int main() {
    const char* json = "{\"hello\": world}"; // Invalid JSON (world not quoted)
    
    Document d;
    if (d.Parse(json).HasParseError()) {
        fprintf(stderr, "\nError(offset %u): %s\n", 
                (unsigned)d.GetErrorOffset(),
                GetParseError_En(d.GetParseError()));
        return 1;
    }
    
    return 0;
}

Using JSON Pointer

#include "rapidjson/document.h"
#include "rapidjson/pointer.h"

int main() {
    Document d;
    d.Parse("{\"users\":[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]}");

    // Access using JSON Pointer
    Value* alice_age = Pointer("/users/0/age").Get(d);
    if (alice_age && alice_age->IsInt()) {
        std::cout << "Alice's age: " << alice_age->GetInt() << std::endl;
    }

    // Set value using JSON Pointer
    Pointer("/users/1/age").Set(d, 26);
    
    // Create new path
    Pointer("/users/2/name").Create(d).SetString("Charlie");
    Pointer("/users/2/age").Create(d).SetInt(35);

    return 0;
}