ProtoJSON encoder/decoder for PB.
The headline API works directly with JSON binary strings: encode/4
returns a JSON-encoded binary, decode/4 parses a JSON-encoded binary.
Parsing and serialisation are performed with OTP's built-in :json module
(OTP 27+), with two ProtoJSON-required customisations baked in:
- JSON
nulldecodes as Elixirnil(and Elixirnilis encoded as the JSONnullliteral) — OTP's default mapping uses the atom:null, which PB does not. - Duplicate JSON object keys are rejected as
kind: :malformed_jsonerrors — OTP's default decoder silently keeps the last occurrence, masking ProtoJSONFieldNameDuplicateviolations.
A secondary surface exposes the underlying term-in/term-out pipeline.
to_term/4 returns a JSON-compatible Elixir term (maps, lists, strings,
numbers, booleans, nil) and from_term/4 accepts one. Use these when
composing with another JSON library or when asserting on the JSON shape
directly.
Like the wire codec, these honor the schema's configured projections: the decoded/accepted message shape follows the schema's native representation (adapters, struct/unwrap), so under a projection the value may be a struct, a tuple, or a bare scalar rather than a plain map.
Supported
All scalar types, enums (by name or integer), repeated fields, maps, oneofs,
proto2 and proto3 (including proto3 optional).
Wrapper messages (google.protobuf.Int32Value, StringValue, BoolValue,
BytesValue, etc.) are serialised as their bare scalar value per ProtoJSON.
google.protobuf.FieldMask is serialised as a single comma-separated string
with each path converted between snake_case (proto) and lowerCamelCase (JSON).
google.protobuf.Duration is serialised as a decimal-seconds string ending
in "s". google.protobuf.Timestamp is serialised as an RFC 3339 / ISO 8601
string in UTC ending in "Z". google.protobuf.Value, Struct, and
ListValue round-trip as bare JSON values (null/number/bool/string),
objects, and arrays respectively. google.protobuf.Any serialises as an
object with a @type URL plus the embedded message — flat-merged when the
embedded message uses the default JSON object form, or under a value
field when the embedded message itself has a custom JSON mapping (other
WKTs, including nested Any). Only the type.googleapis.com/<fqn> URL
prefix is accepted.
Options
:emit_defaults— whentrue, fields without presence that have their default value are emitted instead of omitted. Defaults tofalse.:use_proto_names— whentrue, the encoder emits field names as written in the.protofile (snake_case) rather than lowerCamelCase. Parsers always accept both spellings. Defaults tofalse.:enums_as_ints— whentrue, enums are encoded as their numeric value instead of the enum-value name. Defaults tofalse.:ignore_unknown— whentrue, unknown JSON keys are skipped during decoding. Defaults tofalse(decode/4returns{:error, %PB.ValueError{kind: :unknown_field}}).
Encode (encode/4, to_term/4) accepts :emit_defaults, :use_proto_names,
and :enums_as_ints; decode (decode/4, from_term/4) accepts
:ignore_unknown. Like the core codec, the option set is validated per
direction: an unknown key (including a typo such as emit_default:), an
option meant for the other direction, or a non-boolean value returns
{:error, %PB.OptionError{}} rather than being silently ignored.
Summary
Functions
Decodes a JSON binary string into the map shape used by PB.encode/3.
Returns {:ok, map} or {:error, error} (see PB.Error).
Decodes a JSON binary string into the map shape used by PB.encode/3,
raising PB.Error on failure.
Encodes data (the same shape produced by PB.decode/4) as a JSON
binary string. Returns {:ok, binary} or {:error, error} (see PB.Error).
Encodes data as a JSON binary string, raising PB.Error on failure.
Encodes data as JSON iodata. Returns {:ok, iodata} or
{:error, error} (see PB.Error).
Encodes data as JSON iodata, raising PB.Error on failure.
Decodes a parsed JSON term into the map shape used by PB.encode/3.
Returns {:ok, map} or {:error, error} (see PB.Error).
Decodes a parsed JSON term into the map shape used by PB.encode/3,
raising PB.Error on failure.
Encodes data into a JSON-compatible Elixir term (maps, lists, strings,
numbers, booleans, nil). Returns {:ok, term} or
{:error, error} (see PB.Error).
Encodes data into a JSON-compatible Elixir term, raising PB.Error
on failure.
Types
Functions
@spec decode(binary(), PB.schema_source(), PB.message_name(), opts()) :: {:ok, term()} | {:error, PB.Error.t()}
Decodes a JSON binary string into the map shape used by PB.encode/3.
Returns {:ok, map} or {:error, error} (see PB.Error).
Two ProtoJSON-required behaviours are baked in: JSON null is mapped to
Elixir nil, and duplicate JSON object keys are rejected as
kind: :malformed_json errors.
@spec decode!(binary(), PB.schema_source(), PB.message_name(), opts()) :: term()
Decodes a JSON binary string into the map shape used by PB.encode/3,
raising PB.Error on failure.
This is the bang variant of decode/4.
@spec encode(term(), PB.schema_source(), PB.message_name(), opts()) :: {:ok, binary()} | {:error, PB.Error.t()}
Encodes data (the same shape produced by PB.decode/4) as a JSON
binary string. Returns {:ok, binary} or {:error, error} (see PB.Error).
@spec encode!(term(), PB.schema_source(), PB.message_name(), opts()) :: binary()
Encodes data as a JSON binary string, raising PB.Error on failure.
This is the bang variant of encode/4.
@spec encode_iodata(term(), PB.schema_source(), PB.message_name(), opts()) :: {:ok, iodata()} | {:error, PB.Error.t()}
Encodes data as JSON iodata. Returns {:ok, iodata} or
{:error, error} (see PB.Error).
@spec encode_iodata!(term(), PB.schema_source(), PB.message_name(), opts()) :: iodata()
Encodes data as JSON iodata, raising PB.Error on failure.
This is the bang variant of encode_iodata/4.
@spec from_term(term(), PB.schema_source(), PB.message_name(), opts()) :: {:ok, term()} | {:error, PB.Error.t()}
Decodes a parsed JSON term into the map shape used by PB.encode/3.
Returns {:ok, map} or {:error, error} (see PB.Error).
@spec from_term!(term(), PB.schema_source(), PB.message_name(), opts()) :: term()
Decodes a parsed JSON term into the map shape used by PB.encode/3,
raising PB.Error on failure.
This is the bang variant of from_term/4.
@spec to_term(term(), PB.schema_source(), PB.message_name(), opts()) :: {:ok, term()} | {:error, PB.Error.t()}
Encodes data into a JSON-compatible Elixir term (maps, lists, strings,
numbers, booleans, nil). Returns {:ok, term} or
{:error, error} (see PB.Error).
Use this when composing with a different JSON library or when asserting on the JSON shape directly.
@spec to_term!(term(), PB.schema_source(), PB.message_name(), opts()) :: term()
Encodes data into a JSON-compatible Elixir term, raising PB.Error
on failure.
This is the bang variant of to_term/4.