Protobuf well-known types and their JSON form

In JSON a Timestamp is an RFC 3339 string such as "2026-09-25T14:30:00Z", a Duration is seconds with an s suffix such as "1.5s", an Any is an object with an "@type" URL beside the message's fields, and a wrapper such as Int32Value is the bare value. 64-bit integers are strings.

Updated

Well-known types

TypeJSON formExample
TimestampRFC 3339 string. Written in UTC with Z and 0, 3, 6 or 9 fractional digits; offsets such as +03:00 are accepted when parsing"2026-09-25T14:30:00.500Z"
DurationSeconds as a decimal with an s suffix, negative allowed"300s", "1.500s", "-0.25s"
AnyThe packed message's JSON with an "@type" URL added. A well-known type inside Any goes under "value"{"@type": "type.googleapis.com/shop.v1.Card", "number": "4242"}
StructAny JSON object{"team": "infra", "replicas": 3}
ValueAny JSON value3, "x", true, null
ListValueA JSON array[1, "two", null]
NullValuenullnull
EmptyAn empty object{}
FieldMaskComma-separated paths, each in lowerCamelCase"displayName,address.city"
Int32Value, UInt32Value, FloatValue, DoubleValueThe number itself; null means unset3, 0.5
Int64Value, UInt64ValueThe number as a string"9007199254740993"
BoolValue, StringValueThe value itselftrue, "hello"
BytesValueBase64"aGVsbG8="

Scalars and fields

ProtoJSON
int32, sint32, sfixed32, uint32, fixed32A number. Strings such as "5" are accepted
int64, sint64, sfixed64, uint64, fixed64A string such as "5", since JavaScript numbers lose precision past 2^53. Numbers are accepted
float, doubleA number, or "NaN", "Infinity" or "-Infinity"
booltrue or false
stringA string
bytesBase64, standard with padding when written; URL-safe accepted
enumThe value's name, such as "ROLE_ADMIN". The number is accepted
messageAn object
repeatedAn array
map<K, V>An object; keys are always strings, even for integer keys
field nameslowerCamelCase (run_at is runAt), or the json_name option. Parsers accept the original name too

Worked example

A job message that uses five well-known types:

syntax = "proto3";
package jobs.v1;

import "google/protobuf/duration.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";

message Job {
  string name = 1;
  google.protobuf.Timestamp run_at = 2;
  google.protobuf.Duration timeout = 3;
  google.protobuf.Int32Value retries = 4;
  google.protobuf.FieldMask update_mask = 5;
  google.protobuf.Struct labels = 6;
}

And the JSON a client sends for it:

{
  "name": "nightly-backup",
  "runAt": "2026-09-25T02:00:00Z",
  "timeout": "300s",
  "retries": 3,
  "updateMask": "runAt,timeout",
  "labels": { "team": "infra", "critical": true }
}

Fields left at their defaults can be left out: an absent retries is unset, which is exactly what the wrapper type is for. The .proto to JSON tool writes this skeleton from the message for you.

istek bundles the well-known types, so a .proto that imports google/protobuf/timestamp.proto loads with nothing installed. See istek.

istek, $29 once

macOS 14.0+ · Apple Silicon · no account, no telemetry

Buy istek · $29