ExSQL.Json (exsql v0.1.1)

Copy Markdown

The json1 function family's data layer: a JSON parser/renderer over an order-preserving representation, plus path navigation ($.a.b[0], $[#-1]).

JSON values map to:

  • :null, true, false
  • numbers (integer, float, or preserved real literal token)
  • strings (binaries)
  • {:array, [value]}
  • {:object, [{key, value}]} — pairs in source/insertion order, as SQLite preserves object member order in json_object and rewrites

Hand-rolled rather than JSON/:json because object member order is observable in SQLite's output.

Summary

Functions

RFC 7386 MergePatch, as json_patch() implements it: patch objects merge recursively (null members delete), anything else replaces the target.

Parses $, $.key, $."quoted key", $[2], $[#-1] paths.

Converts a JSON value to its SQL representation (leaves stay scalar, containers render).

The json_type() name for a JSON value.

Writes value at the path. :insert only creates missing leaves, :replace only overwrites existing ones, :set does both. Missing intermediate containers leave the document unchanged, as in SQLite.

Types

object_key()

@type object_key() ::
  binary()
  | {:jsonb_path_key, binary()}
  | {:jsonb_integer_literal, 4, binary(), integer()}
  | {:jsonb_escaped_text, 9, binary(), binary()}
  | {:jsonb_escaped_key, 8 | 9, binary(), binary()}

path_step()

@type path_step() ::
  {:key, binary()} | {:index, non_neg_integer()} | {:last_offset, integer()}

t()

@type t() ::
  :null
  | boolean()
  | number()
  | {:real_literal, binary()}
  | {:jsonb_integer_literal, 4, binary(), integer()}
  | {:jsonb_real_literal, 5 | 6, binary()}
  | {:jsonb_text, 10, binary()}
  | {:jsonb_escaped_text, 8 | 9, binary(), binary()}
  | binary()
  | {:array, [t()]}
  | {:object, [{object_key(), t()}]}

Functions

get(jv, arg2)

@spec get(t(), [path_step()]) :: {:ok, t()} | :missing

merge_patch(target, patch)

@spec merge_patch(t(), t()) :: t()

RFC 7386 MergePatch, as json_patch() implements it: patch objects merge recursively (null members delete), anything else replaces the target.

object_key_text(key)

@spec object_key_text(object_key()) :: binary()

parse(text)

@spec parse(binary()) :: {:ok, t()} | :error

parse_json5(text)

@spec parse_json5(binary()) :: {:ok, t()} | :error

parse_path(arg1)

@spec parse_path(binary()) :: {:ok, [path_step()]} | :error

Parses $, $.key, $."quoted key", $[2], $[#-1] paths.

parse_sqlite_jsonb(blob)

@spec parse_sqlite_jsonb(binary()) :: {:ok, t()} | :error

pretty(jv, indent \\ " ")

@spec pretty(t(), binary()) :: binary()

remove(jv, arg2)

@spec remove(t(), [path_step()]) :: t()

render(jv)

@spec render(t()) :: binary()

sqlite_jsonb_strict?(blob)

@spec sqlite_jsonb_strict?(binary()) :: boolean()

sqlite_jsonb_superficial?(blob)

@spec sqlite_jsonb_superficial?(binary()) :: boolean()

to_sql(n)

@spec to_sql(t()) :: ExSQL.Value.t()

Converts a JSON value to its SQL representation (leaves stay scalar, containers render).

to_sqlite_jsonb(jv)

@spec to_sqlite_jsonb(t()) :: binary()

type_name(n)

@spec type_name(t()) :: binary()

The json_type() name for a JSON value.

write(jv, arg2, value, mode)

@spec write(t(), [path_step()], t(), :insert | :replace | :set) :: t()

Writes value at the path. :insert only creates missing leaves, :replace only overwrites existing ones, :set does both. Missing intermediate containers leave the document unchanged, as in SQLite.