PB.JSON implements ProtoJSON — the canonical protobuf JSON mapping — on top of
the same compiled schema you use for the wire codec.
String in, string out
The headline API works with JSON binary strings:
{:ok, json} = PB.JSON.encode(%{name: "Alice", id: 42}, schema, :"mypackage.Person")
{:ok, decoded} = PB.JSON.decode(json, schema, :"mypackage.Person")Parsing and serialisation use OTP's built-in :json module (OTP 27+) with two
ProtoJSON-required customisations: JSON null maps to Elixir nil (not :null),
and duplicate JSON object keys are rejected as kind: :malformed_json rather than
silently keeping the last one.
Bang variants encode!/4 and decode!/4 are available.
Term in, term out
When composing with another JSON library, or asserting on the JSON shape
directly, use the term-level surface. to_term/4 returns a JSON-compatible Elixir
term (maps, lists, strings, numbers, booleans, nil); from_term/4 accepts one:
{:ok, term} = PB.JSON.to_term(%{name: "Alice"}, schema, :"mypackage.Person")
# => %{"name" => "Alice"}Projections apply
Like the wire codec, JSON honors the schema's configured projections. Under a struct/unwrap representation or an adapter, the value may be a struct, a tuple, or a bare scalar rather than a plain map. See Decoding into structs and Adapters and well-known types.
Well-known types
PB applies the ProtoJSON mappings for well-known types automatically: wrapper
messages serialise as their bare scalar; Duration as a decimal-seconds string
ending in "s"; Timestamp as an RFC 3339 UTC string ending in "Z";
FieldMask as a comma-separated lowerCamelCase path string; Value/Struct/
ListValue as bare JSON values, objects, and arrays; and Any as an object with
a @type URL.
Options
Encode (encode/4, to_term/4) accepts:
:emit_defaults— emit present-less fields at their default value (defaultfalse).:use_proto_names— emit snake_case field names instead of lowerCamelCase (defaultfalse; parsers always accept both).:enums_as_ints— emit enum numeric values instead of names (defaultfalse).
Decode (decode/4, from_term/4) accepts:
:ignore_unknown— skip unknown JSON keys (defaultfalse, which returns akind: :unknown_fielderror).
Options are validated per direction: a typo, a wrong-direction option, or a
non-boolean value returns a PB.OptionError rather than being silently ignored.