JSON processing — the json unit

PXX includes a native, lightweight JSON parser and serializer in the json unit. It features a recursive-descent parser, typed value accessors, canonical round-trip serialization, and pretty-printing.


TJSONValue (JSON Node)

The TJSONValue class represents any node in a JSON tree, such as an object, an array, a string, a number, a boolean, or a null value.

Key Members


Parsing JSON

To parse a JSON string, use the global JSONParse function, which returns the root TJSONValue node:

function JSONParse(const S: AnsiString): TJSONValue;

Error Handling

If the input string is malformed or has trailing junk, JSONParse raises an EJSONError exception (defined in the json unit).


Compiling Example

The following program demonstrates parsing, reading typed values, checking keys, serializing, and handling parse errors. It compiles and runs on the pinned compiler:

program json_demo;

uses json, sysutils;

procedure DemoJsonParsing;
var
  jsonText: AnsiString;
  root, nameVal, ageVal, activeVal, tagsVal: TJSONValue;
  i: Integer;
begin
  // A sample JSON payload
  jsonText := '{"name": "Alice", "age": 30, "active": true, "tags": ["admin", "user"]}';
  
  writeln('Parsing JSON payload...');
  root := JSONParse(jsonText);
  try
    // Accessing object fields by name
    nameVal := root.GetValue('name');
    writeln('Name: ', nameVal.AsString);
    
    ageVal := root.GetValue('age');
    writeln('Age: ', ageVal.AsInteger);
    
    activeVal := root.GetValue('active');
    writeln('Active: ', activeVal.AsBoolean);
    
    // Accessing array items by index
    tagsVal := root.GetValue('tags');
    writeln('Tags count: ', tagsVal.Count);
    for i := 0 to tagsVal.Count - 1 do
      writeln('  Tag ', i, ': ', tagsVal.GetItem(i).AsString);
      
    // Check if a key exists
    if root.HasKey('missing') then
      writeln('Key "missing" is present')
    else
      writeln('Key "missing" is absent');
      
    // Serializing back to JSON strings
    writeln('Compact JSON:');
    writeln(root.ToString(False));
    
    writeln('Pretty JSON:');
    writeln(root.ToString(True));
  finally
    // Free the entire tree recursively
    root.FreeTree;
  end;
end;

procedure DemoJsonError;
var
  root: TJSONValue;
begin
  writeln('--- Testing Parse Error ---');
  try
    // Malformed JSON (missing closing brace)
    root := JSONParse('{"name": "Alice"');
    root.FreeTree;
  except
    on E: EJSONError do
      writeln('Caught expected JSON parse error: ', E.Reason);
  end;
end;

begin
  DemoJsonParsing;
  DemoJsonError;
end.

Output:

Parsing JSON payload...
Name: Alice
Age: 30
Active: TRUE
Tags count: 2
  Tag 0: admin
  Tag 1: user
Key "missing" is absent
Compact JSON:
{"name":"Alice","age":30,"active":true,"tags":["admin","user"]}
Pretty JSON:
{
  "name": "Alice",
  "age": 30,
  "active": true,
  "tags": [
    "admin",
    "user"
  ]
}
--- Testing Parse Error ---
Caught expected JSON parse error: expected value