DocShell.Json.Canonical (DocShell v0.4.0)

Copy Markdown View Source

Computes reproducible JSON bytes and content digests at serialization boundaries.

Native JSON values are validated and encoded directly, avoiding a redundant encode/decode allocation cycle when hashing an already decoded corpus. Other values pass through Jason with strict object keys, so protocol encoders retain their wire representation and atom/string key collisions fail before any information is discarded. Objects are then sorted by UTF-8 key bytes; array order and native scalar types remain unchanged. The resulting compact encoding preserves the original DocShell collection digest format. It is not an implementation of RFC 8785 (in particular, numbers use Jason's encoding).

Both functions return tagged errors, including exceptions from host encoders. They neither coerce unsupported metadata nor hide encoding errors in inspected strings. Use DocShell.Json.normalize/1 when coercion is explicitly intended.

Summary

Types

Values supported by Jason, subject to UTF-8 and unique encoded keys.

Functions

Hashes canonical JSON bytes as a lowercase, prefixed SHA-256 digest.

Encodes a value to compact canonical JSON, rejecting ambiguous object keys.

Types

encodable()

@type encodable() ::
  atom()
  | number()
  | String.t()
  | struct()
  | [encodable()]
  | %{optional(atom() | String.t()) => encodable()}

Values supported by Jason, subject to UTF-8 and unique encoded keys.

Functions

digest(value)

@spec digest(term()) :: {:ok, String.t()} | {:error, term()}

Hashes canonical JSON bytes as a lowercase, prefixed SHA-256 digest.

encode(value)

@spec encode(term()) :: {:ok, binary()} | {:error, term()}

Encodes a value to compact canonical JSON, rejecting ambiguous object keys.