Skip to content

Protobuf supports complex, hierarchical data structures. You can define messages within other messages, or use previously defined messages as field types.

Composition lets you build reusable data models shared across services. For example, a Location message can be used across User, Event, and Office messages.

On the wire, embedded messages are "length-delimited", so a decoder can skip the entire sub-message if it doesn't have the schema for it.

message Result {
  string url = 1;
  string title = 2;
}

message SearchResponse {
  Result top_result = 1;
}
JSON
{
  "topResult": {
    "url": "https://protobuf.com/",
    "title": "Protobuf Explained"
  }
}

An embedded message travels as a block: a byte count up front, then the inner message's own bytes.

On the Bytes tab, click the outer segment: the byte count in front is what lets a decoder skip a sub-message it doesn't understand.

schema.proto
edition = "2024";

package demo.v1;

message SearchResponse {
  Result top_result = 1;
  repeated Result results = 2;
}

message Result {
  string url = 1;
  string title = 2;
}
Input JSON (editable)
{
  "topResult": {
    "url": "https://protobuf.com/",
    "title": "Protobuf Explained"
  }
}
ProtoJSON

Compiling the schema...

Next

Repeated Fields

Representing lists in Protobuf with repeated fields, and how packed encoding stores repeated scalars in a single length-prefixed block.