Predicator.Conformance.JSON (predicator v8.0.0)

Copy Markdown View Source

A deterministic JSON writer for the conformance corpus (px-35i.4).

The built-in JSON.encode!/1 does not guarantee map key order, which makes its output unusable for a byte-compared, checked-in corpus: two semantically identical maps built by inserting keys in a different order could encode differently, turning the staleness test red for no reason. encode_canonical/1 fixes that by walking the term itself, sorting object keys by codepoint, and emitting no incidental whitespace - JSON.encode!/1 is still used underneath for scalar and string escaping, so the escaping rules stay the standard library's.

encode_lines/1 is the shipped corpus format: a list of objects, one per line, so that changing a single case is a one-line diff instead of a whole-file rewrite.

Summary

Types

A term encodable as JSON: what JSON.decode/1 can produce, plus atom map keys.

Functions

Encodes term as canonical JSON: object keys sorted by codepoint, no incidental whitespace.

Encodes a list of terms as the shipped corpus format: one canonical-JSON object per line, each terminated by \n.

Types

json_value()

@type json_value() ::
  nil
  | boolean()
  | number()
  | binary()
  | [json_value()]
  | %{optional(binary() | atom()) => json_value()}

A term encodable as JSON: what JSON.decode/1 can produce, plus atom map keys.

Functions

encode_canonical(term)

@spec encode_canonical(json_value()) :: binary()

Encodes term as canonical JSON: object keys sorted by codepoint, no incidental whitespace.

Examples

iex> Predicator.Conformance.JSON.encode_canonical(%{"b" => 1, "a" => 2})
~s({"a":2,"b":1})

iex> Predicator.Conformance.JSON.encode_canonical([1, "two", true, nil])
~s([1,"two",true,null])

encode_lines(items)

@spec encode_lines([json_value()]) :: binary()

Encodes a list of terms as the shipped corpus format: one canonical-JSON object per line, each terminated by \n.

Examples

iex> Predicator.Conformance.JSON.encode_lines([%{"id" => 1}, %{"id" => 2}])
~s({"id":1}\n{"id":2}\n)