glazer (glazer v0.1.4)

View Source

Fast JSON encoding and decoding using the glaze C++ library.

By default JSON null is represented as the atom null. To change it application-wide, set the null env key in your config:

{glazer, [{null, nil}]}.

See also [https://github.com/stephenberry/glaze]

Summary

Functions

Decode a JSON binary or iolist to an Erlang term. JSON objects are returned as maps (default).

Decode a JSON binary or iolist to an Erlang term with options.

Decode a JSON number string to a big integer.

Encode an Erlang term to a JSON binary.

Encode an Erlang term to a JSON binary with options.

Encode a big integer to its JSON string representation.

Minify a JSON binary or iolist, removing all unnecessary whitespace.

Pretty-print a JSON binary or iolist with two-space indentation.

Locate the end of the next complete top-level JSON value in Bin, without decoding it.

Resume scanning Bin (the unconsumed remainder plus newly-appended bytes) from ScanState.

Create a new incremental decoder for feeding JSON in chunks (e.g. from a socket or file), useful when a complete document isn't available up front or when a stream contains a sequence of concatenated/whitespace-separated JSON values (e.g. newline-delimited JSON).

Create a new incremental decoder, passing Opts through to every decode/2 call.

Signal end-of-stream: decode any remaining buffered bytes as a final value (useful for a trailing bare scalar, e.g. a lone number or true/null, which the scanner can't otherwise distinguish from a value that's still being written to mid-chunk).

Feed a chunk of bytes into the decoder, returning any complete JSON values found so far (in order) along with the updated decoder.

Types

decode_opt()

-type decode_opt() ::
          return_maps | object_as_tuple | use_nil |
          {null_term, atom()} |
          {keys, atom | existing_atom | binary}.

decode_opts()

-type decode_opts() :: [decode_opt()].

Decode options:

  • return_maps - decode JSON objects as Erlang maps (default)
  • object_as_tuple - decode JSON objects as {[{K, V}]} proplists
  • use_nil - use the atom nil for JSON null
  • {null_term, Atom} - use Atom for JSON null
  • {keys, atom} - decode object keys as atoms
  • {keys, existing_atom} - decode keys as existing atoms, fall back to binary
  • {keys, binary} - decode keys as binaries (default)

encode_opt()

-type encode_opt() :: pretty | uescape | force_utf8 | use_nil | {null_term, atom()}.

encode_opts()

-type encode_opts() :: [encode_opt()].

Encode options:

  • pretty - pretty-print the JSON output
  • uescape - escape non-ASCII characters as \uXXXX sequences
  • force_utf8 - fix invalid UTF-8 sequences before encoding
  • use_nil - encode the atom nil as JSON null
  • {null_term, Atom} - encode Atom as JSON null

scan_state()

-type scan_state() :: tuple().

stream_decoder()

-opaque stream_decoder()

Functions

decode(Input)

-spec decode(binary() | iolist()) -> term().

Decode a JSON binary or iolist to an Erlang term. JSON objects are returned as maps (default).

decode(Input, Opts)

-spec decode(binary() | iolist(), decode_opts()) -> term().

Decode a JSON binary or iolist to an Erlang term with options.

decode_bigint(NumberString)

-spec decode_bigint(binary() | iolist()) -> {ok, integer()} | {error, binary()}.

Decode a JSON number string to a big integer.

encode(Data)

-spec encode(term()) -> binary().

Encode an Erlang term to a JSON binary.

encode(Data, Opts)

-spec encode(term(), encode_opts()) -> binary().

Encode an Erlang term to a JSON binary with options.

encode_bigint(BigInt)

-spec encode_bigint(integer()) -> {ok, binary()} | {error, binary()}.

Encode a big integer to its JSON string representation.

minify(Input)

-spec minify(binary() | iolist()) -> {ok, binary()} | {error, binary()}.

Minify a JSON binary or iolist, removing all unnecessary whitespace.

prettify(Input)

-spec prettify(binary() | iolist()) -> {ok, binary()} | {error, binary()}.

Pretty-print a JSON binary or iolist with two-space indentation.

scan(Bin)

-spec scan(binary() | iolist()) -> {complete, non_neg_integer()} | {incomplete, scan_state()}.

Locate the end of the next complete top-level JSON value in Bin, without decoding it.

Returns:

  • {complete, EndOffset} - a complete value spans binary:part(Bin, 0, EndOffset); the rest of Bin (if any) is left over for the next call
  • {incomplete, ScanState} - Bin doesn't yet contain a complete value; feed more data via scan/2 once it's available, passing the entire unconsumed remainder (this Bin, with new bytes appended) plus ScanState

This is the low-level primitive behind stream_feed/2; most callers should use the stream_* API instead.

scan(Bin, ScanState)

-spec scan(binary() | iolist(), scan_state()) ->
              {complete, non_neg_integer()} | {incomplete, scan_state()}.

Resume scanning Bin (the unconsumed remainder plus newly-appended bytes) from ScanState.

stream_decoder()

-spec stream_decoder() -> stream_decoder().

Create a new incremental decoder for feeding JSON in chunks (e.g. from a socket or file), useful when a complete document isn't available up front or when a stream contains a sequence of concatenated/whitespace-separated JSON values (e.g. newline-delimited JSON).

Decoding itself is not incremental — each complete top-level value is still decoded in a single pass via decode/2 using the library's fast whole-buffer decoder. Only the boundary detection (finding where one value ends and the next begins) is incremental, via a small byte-scanner that tracks nesting/string state across chunks.

Example

1> D0 = glazer:stream_decoder(),
2> {Vals1, D1} = glazer:stream_feed(D0, <<"{\\"a\\":1} {\\"b\\":">>),
3> Vals1.
[#{<<"a">> => 1}]
4> {Vals2, _D2} = glazer:stream_feed(D1, <<"2}">>),
5> Vals2.
[#{<<"b">> => 2}]

stream_decoder(Opts)

-spec stream_decoder(decode_opts()) -> stream_decoder().

Create a new incremental decoder, passing Opts through to every decode/2 call.

stream_eof/1

-spec stream_eof(stream_decoder()) -> {ok, [term()]} | {error, term()}.

Signal end-of-stream: decode any remaining buffered bytes as a final value (useful for a trailing bare scalar, e.g. a lone number or true/null, which the scanner can't otherwise distinguish from a value that's still being written to mid-chunk).

Returns {ok, [Term]} with zero or one trailing value, or {error, Reason} if the remaining bytes don't form a complete value.

stream_feed/2

-spec stream_feed(stream_decoder(), binary() | iolist()) -> {[term()], stream_decoder()}.

Feed a chunk of bytes into the decoder, returning any complete JSON values found so far (in order) along with the updated decoder.

Raises the same exceptions as decode/2 (e.g. {parse_error, Reason}) if a value that the scanner deemed complete fails to decode.