In practice, virtually nobody hand-writes serializers. Teams generate code from .proto files. The generated code provides typed message constructors, binary serialization, JSON mapping, and service bindings depending on the plugin.
edition = "2024"; package intro.v1; message User { int64 id = 1; string name = 2; uint32 age = 3; float height_cm = 4; double weight_kg = 5; bool verified = 6; }
From Contract to Runtime API
This schema defines a User message with six fields. Each field has a type, a generated-code name, and a stable field number used by the binary format.
Once code is generated from this schema, you can:
- Instantiate: Create
Userobjects in your language with type checking and editor support. - Serialize: Convert objects into compact binary buffers for transmission or storage.
- Validate: Reject data that doesn't match the schema's structure before it reaches application logic.
Generating Code with buf
This guide uses the Buf CLI, which keeps generation declarative with a buf.gen.yaml file: check it into your repo and everyone on the team generates the same output with one command. The remote plugins in this example run on the Buf Schema Registry, so there are no plugin binaries to install locally.
version: v2 plugins: - remote: buf.build/bufbuild/es out: web/src/gen opt: target=ts - remote: buf.build/protocolbuffers/go out: gen/go opt: paths=source_relative
$ buf generateGenerating with protoc
protoc is the reference compiler for Protobuf. Plugins (like protoc-gen-es) are installed as executables on your system's PATH and selected with command-line flags.
$ npm install --save-dev @bufbuild/protoc-gen-es $ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ protoc --es_out=web/src/gen --es_opt=target=ts \
--go_out=gen/go --go_opt=paths=source_relative \
proto/intro/v1/user.protoUsing the Generated Code
With code generated by protobuf-es, the schema becomes a native TypeScript API.
import { create, toBinary, toJsonString } from "@bufbuild/protobuf"; import { UserSchema } from "./gen/intro/v1/user_pb"; const user = create(UserSchema, { id: 1042n, name: "cyber_ninja", age: 28, verified: true, }); const bytes = toBinary(UserSchema, user); const json = toJsonString(UserSchema, user); console.log("JSON Output:", json); console.log("Binary Output:", bytes);
Further Reading
- The modern Protobuf workflow
How schema-first development fits together end to end, from lint to generation to breaking-change checks.
- Protobuf-ES: the TypeScript runtime we all deserve
The design behind the generated TypeScript this page runs in your browser.
- Getting started in Go
The official Go tutorial: generate code from a .proto and use it to write and read messages.
- Getting started in Python
A guided tour of Protobuf in Python, from generation through the runtime API.
- Getting started in TypeScript
The Protobuf-ES guide: the same runtime the interactive demos on this page use.
- Getting started in Java
The official Java tutorial.
- Getting started in Kotlin
The official Kotlin tutorial.
- Getting started in C++
The official C++ tutorial.
- Getting started in C#
The official C# tutorial.
- Getting started in Dart
The official Dart tutorial.
Next
Advanced
Imports and editions, field presence, unknown fields, and which schema changes break clients that are already deployed.