Skip to content

ddn.data.json5

JSON5 parsing and serialization support for the D programming language.

Overview

The ddn.data.json5 module provides comprehensive support for JSON5, a superset of JSON that aims to be easier for humans to write and maintain. It includes a full-featured parser and writer that maps JSON5 values to and from ddn.var.

JSON5 Features Supported

JSON5 extends standard JSON with several human-friendly features:

Feature Description
Comments Single-line (//) and block (/* */) comments
Trailing commas Allowed in arrays and objects
Unquoted keys Object keys can be unquoted if they are valid identifiers
Single-quoted strings Strings can use 'single quotes'
Multi-line strings Line continuations with backslash
Hexadecimal numbers 0xDEADBEEF notation
Leading/trailing decimals .5 and 5. are valid
Explicit plus sign +1.5 is valid
Special numbers NaN, Infinity, -Infinity
UTF-8 BOM Accepted at the beginning of input

Type Mapping

JSON5 values are mapped to ddn.var types as follows:

JSON5 Value var.Type
null NULL
true, false BOOL
Integer (fits long) LONG
Integer (fits ulong, non-negative) ULONG
Floating point, NaN, Infinity DOUBLE
String (single or double quoted) STRING
Array ARRAY
Object OBJECT

Usage Examples

Parsing JSON5

import ddn.data.json5;
import ddn.var;

Json5Error err;
var v;

// Parse JSON5 with trailing commas and unquoted keys
if (parseJSON5(v, "{a: 1, b: 'hello',}", err)) {
    assert(v["a"].as!long == 1);
    assert(v["b"].as!string == "hello");
} else {
    // Handle parse error
    writeln("Error at line ", err.line, ": ", err.message);
}

Writing JSON5

import ddn.data.json5;
import ddn.var;

var data;
data["name"] = "example";
data["values"] = [1, 2, 3];
data["active"] = true;

// Compact JSON5 output
string json5 = toJSON5(data);
// Output: {active:true,name:'example',values:[1,2,3]}

// Strict JSON output
string json = toJSON(data);
// Output: {"active":true,"name":"example","values":[1,2,3]}

Pretty Printing

Json5WriteOptions opts;
opts.pretty = true;
opts.indentWidth = 2;

string pretty = toJSON5(data, opts);
/* Output:
{
  active: true,
  name: 'example',
  values: [
    1,
    2,
    3,
  ],
}
*/

Minifying JSON5

// Remove comments and whitespace
string compact = minify("{ a: 1, // comment\n b: 2, }");
assert(compact == "{a:1,b:2,}");

Writer Behavior

Strict JSON Mode

When using toJSON() or writeMode = JSON:

  • All keys are quoted with double quotes
  • Strings use double quotes with standard escaping
  • NaN and Infinity are emitted as null (not valid in JSON)
  • No trailing commas
  • No comments

JSON5 Mode

When using toJSON5() or writeMode = JSON5:

  • Keys are unquoted when they are valid identifiers
  • Strings prefer single quotes (fewer escapes needed)
  • NaN, Infinity, -Infinity are preserved
  • Trailing commas are added (configurable)

Error Handling

The parser provides detailed error information:

Json5Error err;
var v;
if (!parseJSON5(v, "{ invalid }", err)) {
    writefln("Parse error at %d:%d - %s", err.line, err.column, err.message);
}

Performance Features

  • Scratch buffers: Use Json5WriteScratch for reduced allocations in hot paths
  • Depth limits: Configurable maxDepth prevents stack overflow on deeply nested input
  • Fast-path parsing: Simple literals are parsed efficiently
// Reuse scratch buffers for multiple serializations
Json5WriteScratch scratch;
foreach (item; items) {
    string json = toJSON5(item, Json5WriteOptions.init, scratch);
    // process json...
}

See Also

  • ddn.var — Dynamic value type used for JSON5 data representation.
  • ddn.adam — Memory-efficient alternative to var.
  • ddn.util.json_escape — String escaping utilities used internally.