Pretty-Printing JSON

Purpose

The Pretty-Printing JSON subtopic addresses the need to convert in-memory JSON structures into readable, well-formatted JSON text. While the parent topic JSON Serialization and Testing covers the broader capability of serializing JSON data and verifying parser correctness, this subtopic focuses specifically on formatting output with indentation, line breaks, and proper escaping. This enhances human readability for debugging, logging, or configuration files, where compact representations are insufficient.

Functionality

This subtopic provides a suite of functions designed to traverse the json_value tree and produce formatted JSON output supporting:

The core printing logic is implemented via recursive functions that pattern-match on the JSON value type and call appropriate pretty-print helpers. For example:

These functions work together to generate a clean, human-friendly JSON serialization that respects JSON syntax rules and maintains fidelity to the original data.

Key workflows

Illustrative snippet

static void print_value(const json_value *v, int indent, FILE *out) {
  if (!v) {
    fputs("null", out);
    return;
  }
  switch (v->type) {
  case J_NULL:
    fputs("null", out);
    break;
  case J_STRING:
    print_string_escaped(out, v->u.string.ptr, v->u.string.len);
    break;
  case J_ARRAY:
    print_array_compact(v, out);
    break;
  case J_OBJECT:
    fputs("{\n", out);
    for (size_t i = 0; i < v->u.object.count; ++i) {
      if (i) fputs(",\n", out);
      print_indent(out, indent + 1);
      json_object *e = &v->u.object.items[i];
      print_string_escaped(out, e->ptr, e->len);
      fputs(": ", out);
      print_value(e->value, indent + 1, out);
    }
    fputc('\n', out);
    print_indent(out, indent);
    fputc('}', out);
    break;
  default:
    // Other types handled similarly
    break;
  }
}

This function clearly illustrates the recursive structure, indentation, and formatting logic central to pretty-printing.

Integration

The pretty-printing functionality is a crucial component of the parent topic JSON Serialization and Testing. It complements the parsing capabilities from JSON Parsing and Representation by enabling the reverse operation: transforming parsed in-memory JSON values back into human-readable text.

Thus, pretty-printing acts as the presentation layer that translates the structured JSON data back into a clean textual form, bridging in-memory representation and external representation.

Diagram

flowchart TD
Start[Input json_value Tree] --> PrintValue["print_value()"]
PrintValue -->|J_OBJECT| PrintObject["print each property\nwith indent & line breaks"]
PrintValue -->|J_ARRAY| PrintArray["print elements\ncompact inline"]
PrintValue -->|J_STRING| PrintString["escape & quote"]
PrintValue -->|J_NUMBER/BOOLEAN/NULL| PrintPrimitive["print raw text"]
PrintObject --> RecursivePrintValue["print_value() calls recursively"]
RecursivePrintValue --> End[Formatted JSON Output]

This flowchart illustrates the recursive dispatch mechanism: print_value() inspects the JSON type and delegates to specialized print functions, with objects causing nested recursive calls with increased indentation, arrays printed inline, and primitives printed directly. The process culminates in a formatted JSON text output.