This project provides a lightweight, header-only JSON library in C++ (json.hpp) for creating, parsing, validating, and manipulating JSON documents. It also includes three example programs:
validate-json.cpp— validates JSON files and benchmarks parsing timecreate-json.cpp— demonstrates programmatic JSON constructionmanipulate-json.cpp— demonstrates safe navigation and modification of JSON data
- Inspiration: Coding Challenges JSON Parser
- Data Structure Credits: Stack Overflow: Data types for representing JSON in C
- Mimic (imperfectly) Python’s
jsonmodule withloadsanddumps. - Prefer throwing descriptive errors over silently returning invalid values.
- Use
std::vectorfor both arrays and objects to preserve insertion order. - Support arbitrary nesting depth.
- Expose a high-level, safe view abstraction (
JSONHandle) over raw node pointers.
- Compiler: C++23-capable compiler (tested with
g++) - CMake: for building and running tests
- json.hpp — Header-only JSON library
- validate-json.cpp — Validates JSON files and benchmarks parsing time
- create-json.cpp — Demonstrates JSON creation
- manipulate-json.cpp — Demonstrates JSON navigation and modification
- test/ — Test JSON files (
passXX.json,failXX.json,benchXX.json)- Includes additional tests from
JSONTestSuite under
test/extras/
- Includes additional tests from
JSONTestSuite under
cmake -S . -B build
cmake --build build -j4This produces the following executables in build/:
validate-jsoncreate-jsonmanipulate-json
Tests are registered with CTest.
cd build
ctestTo see full output from the validator:
ctest --verbose --test-dir buildExample from create-json.cpp:
JSON::JSONNodePtr one = JSON::helper::createNode(1);
JSON::JSONNodePtr two = JSON::helper::createNode(2);
JSON::JSONNodePtr arr = JSON::helper::createArray("array", {one, two});
JSON::JSONNodePtr num = JSON::helper::createNode("number", 123);
JSON::JSONNodePtr str = JSON::helper::createNode("string", "Hello World");
JSON::JSONNodePtr root = JSON::helper::createObject({arr, num, str});
std::cout << JSON::Parser::dumps(root) << "\n";Output:
{"array":[1,2],"number":123,"string":"Hello World"}JSONNode— Base class for all nodesJSONValueNode— Simple values (string,number,bool,null)JSONArrayNode— Array of JSON nodesJSONObjectNode— Object of key–value pairs
JSONHandle is a lightweight wrapper around JSONNodePtr that provides a safer and more expressive API for navigating and manipulating JSON trees.
It behaves like a non-owning view with Python-like ergonomics while preserving strict type semantics.
JSONHandle root = Parser::loads(json_string);
auto value = root["config"]["threads"];- Returns an empty handle if:
- The node type is incorrect
- The key or index does not exist
- Never throws
auto threads = root.at("config").at("threads");-
Throws
std::runtime_errorif:- The node is not an object or array
- The key or index does not exist
int threads = root["threads"].to<int>();
std::string name = root["name"].to<std::string>();- Valid only for value nodes
- Throws if the type does not match
- Returns a default-constructed value if the handle is empty
for (JSONHandle child : root["items"]) {
std::cout << child.str() << "\n";
}- Arrays iterate over elements
- Objects iterate over values (in insertion order)
- Value nodes iterate as empty ranges
auto &obj = root.cast<JSONObjectNode>();
auto &arr = root["items"].cast<JSONArrayNode>();- Throws on invalid casts
- Intended for advanced use cases
root.str(); // pretty-printed (default)
root.str(false); // compactstr() is a convenience wrapper around the parser’s dump functionality.
Parses a JSON string and returns a JSONHandle.
Serializes a JSON node into a string (pretty or compact).
JSONHandleis cheap to copy (wraps ashared_ptr)- Invalid access never causes undefined behavior
- Iteration order matches insertion order
- Exit codes from
validate-jsonintegrate cleanly with CTest
For additional examples and details, refer directly to the source files in this repository.