ProtoJSON Format

Describes the spec details of the canonical JSON representation for Protobuf messages.

Protobuf supports a canonical encoding in JSON, making it easier to share data with systems that do not support the standard protobuf binary wire format.

This page specifies the format, but a number of additional edge cases which define a conformant ProtoJSON parser are covered in the Protobuf Conformance Test Suite and are not exhaustively detailed here.

Non-goals of the Format

Cannot Represent Some JSON schemas

The ProtoJSON format is designed to be a JSON representation of schemas which are expressible in the Protobuf schema language.

It may be possible to represent many pre-existing JSON schemas as a Protobuf schema and parse it using ProtoJSON, but it is not designed to be able to represent arbitrary JSON schemas.

For example, there is no way to express in Protobuf schema to write types that may be common in JSON schemas like number[][] or number|string.

It is possible to use google.protobuf.Struct and google.protobuf.Value types to allow arbitrary JSON to be parsed into a Protobuf schema, but these only allow you to capture the values as schemaless unordered key-value maps.

Not as efficient as the binary wire format

ProtoJSON Format is not as efficient as binary wire format and never will be.

The converter uses more CPU to encode and decode messages and (except in rare cases) encoded messages consume more space.

Does not have as good schema-evolution guarantees as binary wire format

ProtoJSON format does not support unknown fields, and it puts field and enum value names into encoded messages which makes it much harder to change those names later. Removing fields is a breaking change that will trigger a parsing error.

See JSON Wire Safety below for more details.

Format Description

Representation of each type

The following table shows how data is represented in JSON files.

Protobuf typeJSONJSON exampleNotes
messageobject{"fooBar": v, "g": null, ...}Generates JSON objects.

Keys are serialized as lowerCamelCase of field name. See Field Names for more special cases regarding mapping of field names to object keys.

Well-known types have special representations, as described in the Well-known types table.

null is valid for any field and leaves the field unset. See Null Values for clarification about the semantic behavior of null values.

enumstring"FOO_BAR"The name of the enum value as specified in proto is used. Parsers accept both enum names and integer values. See Enum Aliasing for details on enums with aliases.
map<K,V>object{"k": v, ...}All keys are converted to strings (object keys in JSON can only be strings).
repeated Varray[v, ...]
booltrue, falsetrue, false
stringstring"Hello World!"
bytesbase64 string"YWJjMTIzIT8kKiYoKSctPUB+"JSON value will be the data encoded as a string using standard base64 encoding with paddings. Either standard or URL-safe base64 encoding with/without paddings are accepted.
int32, fixed32, uint32number1, -10, 0JSON value will be a number. Either numbers or strings are accepted. Empty strings are invalid. Exponent notation (such as 1e2) is accepted in both quoted and unquoted forms.
int64, fixed64, uint64string"1", "-10"JSON value will be a decimal string. Either numbers or strings are accepted. Empty strings are invalid. Exponent notation (such as 1e2) is accepted in both quoted and unquoted forms. See Strings for int64s for the explanation why strings are used for int64s.
float, doublenumber1.1, -10.0, 0, "NaN", "Infinity"JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity". Either numbers or strings are accepted. Empty strings are invalid. Exponent notation is also accepted.

Well-Known Types

Some messages in the google.protobuf package have a special representation when represented in JSON.

No message type outside of the google.protobuf package has a special ProtoJSON handling; for example, types in google.types package are represented with the neutral representation.

Message typeJSONJSON exampleNotes
Anyobject{"@type": "url", "f": v, ... }See Any
Timestampstring"1972-01-01T10:00:20.021Z"Uses RFC 3339 (see clarification). Generated output will always be Z-normalized with 0, 3, 6 or 9 fractional digits. Offsets other than "Z" are also accepted.
Durationstring"1.000340012s", "1s"Generated output always contains 0, 3, 6, or 9 fractional digits, depending on required precision, followed by the suffix "s". Accepted are any fractional digits (also none) as long as they fit into nanoseconds precision and the suffix "s" is required. This is not RFC 3339 'duration' format (see Durations for clarification).
Structobject{ ... }Any JSON object. See struct.proto.
Wrapper typesvarious types2, "2", "foo", true, "true", null, 0, ...Wrappers use the same representation in JSON as the wrapped primitive type, except that null is allowed and preserved during data conversion and transfer.
FieldMaskstring