Documentation Index
Fetch the complete documentation index at: https://mintlify.com/protocolbuffers/protobuf/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks you through the core Protocol Buffers workflow using the address book example from the protobuf repository. You will define a schema, compile it, and use the generated code to serialize and parse messages.
Before you begin, make sure you have installed protoc and the runtime library for your language. See the Installation guide for instructions.
Define a .proto file
Create a file named addressbook.proto. This schema defines two messages: Person (with nested PhoneNumber and PhoneType) and AddressBook.syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
option java_multiple_files = true;
option java_package = "com.example.tutorial.protos";
option java_outer_classname = "AddressBookProtos";
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
A few things to note:
syntax = "proto3" selects the proto3 language version.
- Field numbers (e.g.,
= 1, = 2) uniquely identify each field in the binary encoding. They must not change once your message type is in use.
- The
repeated keyword means the field can appear zero or more times (equivalent to a list).
import "google/protobuf/timestamp.proto" pulls in a well-known type bundled with protobuf.
Compile with protoc
Run protoc against your .proto file and specify the output directory for your target language. Python
Java
C++
C#
Ruby
PHP
protoc --python_out=. addressbook.proto
This generates addressbook_pb2.py in the current directory.To also generate a .pyi type stub for IDE support:protoc --python_out=pyi_out:. addressbook.proto
protoc --java_out=${OUTPUT_DIR} addressbook.proto
Because java_multiple_files = true is set in the schema, protoc generates a separate .java file for each top-level message type (Person.java, AddressBook.java, etc.) in the package directory com/example/tutorial/protos/.protoc --cpp_out=. addressbook.proto
This generates addressbook.pb.h and addressbook.pb.cc.protoc --csharp_out=. addressbook.proto
protoc --ruby_out=. addressbook.proto
protoc --php_out=. addressbook.proto
Make sure the version of the language runtime you install matches (or is newer than) the version of protoc you compiled with.
Write data
Use the generated classes to build and serialize a message. The following examples read an address book from a file, add a person, and write it back out.import addressbook_pb2
import sys
def PromptForAddress(person):
person.id = int(input("Enter person ID number: "))
person.name = input("Enter name: ")
email = input("Enter email address (blank for none): ")
if email != "":
person.email = email
while True:
number = input("Enter a phone number (or leave blank to finish): ")
if number == "":
break
phone_number = person.phones.add()
phone_number.number = number
type = input("Is this a mobile, home, or work phone? ")
if type == "mobile":
phone_number.type = addressbook_pb2.Person.MOBILE
elif type == "home":
phone_number.type = addressbook_pb2.Person.HOME
elif type == "work":
phone_number.type = addressbook_pb2.Person.WORK
else:
print("Unknown phone type; leaving as default value.")
address_book = addressbook_pb2.AddressBook()
# Read the existing address book.
try:
with open(sys.argv[1], "rb") as f:
address_book.ParseFromString(f.read())
except IOError:
print(sys.argv[1] + ": File not found. Creating a new file.")
# Add an address.
PromptForAddress(address_book.people.add())
# Write the new address book back to disk.
with open(sys.argv[1], "wb") as f:
f.write(address_book.SerializeToString())
import com.example.tutorial.protos.AddressBook;
import com.example.tutorial.protos.Person;
import com.google.protobuf.util.Timestamps;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
class AddPerson {
static Person PromptForAddress(BufferedReader stdin,
PrintStream stdout) throws Exception {
Person.Builder person = Person.newBuilder();
stdout.print("Enter person ID: ");
person.setId(Integer.valueOf(stdin.readLine()));
stdout.print("Enter name: ");
person.setName(stdin.readLine());
stdout.print("Enter email address (blank for none): ");
String email = stdin.readLine();
if (email.length() > 0) {
person.setEmail(email);
}
while (true) {
stdout.print("Enter a phone number (or leave blank to finish): ");
String number = stdin.readLine();
if (number.length() == 0) break;
Person.PhoneNumber.Builder phoneNumber =
Person.PhoneNumber.newBuilder().setNumber(number);
stdout.print("Is this a mobile, home, or work phone? ");
String type = stdin.readLine();
if (type.equals("mobile")) {
phoneNumber.setType(Person.PhoneType.MOBILE);
} else if (type.equals("home")) {
phoneNumber.setType(Person.PhoneType.HOME);
} else if (type.equals("work")) {
phoneNumber.setType(Person.PhoneType.WORK);
} else {
stdout.println("Unknown phone type. Using default.");
}
person.addPhones(phoneNumber);
person.setLastUpdated(Timestamps.now());
}
return person.build();
}
public static void main(String[] args) throws Exception {
AddressBook.Builder addressBook = AddressBook.newBuilder();
try {
FileInputStream input = new FileInputStream(args[0]);
try {
addressBook.mergeFrom(input);
} finally {
input.close();
}
} catch (FileNotFoundException e) {
System.out.println(args[0] + ": File not found. Creating a new file.");
}
addressBook.addPeople(
PromptForAddress(
new BufferedReader(new InputStreamReader(System.in)),
System.out));
FileOutputStream output = new FileOutputStream(args[0]);
try {
addressBook.build().writeTo(output);
} finally {
output.close();
}
}
}
#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
using google::protobuf::util::TimeUtil;
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, '\n');
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) break;
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << "Unknown phone type. Using default." << endl;
}
}
*person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
}
int main(int argc, char* argv[]) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
tutorial::AddressBook address_book;
{
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << ": File not found. Creating a new file." << endl;
} else if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
PromptForAddress(address_book.add_people());
{
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
Read data
Parse a serialized file and iterate over the messages it contains.import addressbook_pb2
import sys
def ListPeople(address_book):
for person in address_book.people:
print("Person ID:", person.id)
print(" Name:", person.name)
if person.email != "":
print(" E-mail address:", person.email)
for phone_number in person.phones:
if phone_number.type == addressbook_pb2.Person.MOBILE:
print(" Mobile phone #:", end=" ")
elif phone_number.type == addressbook_pb2.Person.HOME:
print(" Home phone #:", end=" ")
elif phone_number.type == addressbook_pb2.Person.WORK:
print(" Work phone #:", end=" ")
print(phone_number.number)
address_book = addressbook_pb2.AddressBook()
with open(sys.argv[1], "rb") as f:
address_book.ParseFromString(f.read())
ListPeople(address_book)
import com.example.tutorial.protos.AddressBook;
import com.example.tutorial.protos.Person;
import java.io.FileInputStream;
class ListPeople {
static void Print(AddressBook addressBook) {
for (Person person : addressBook.getPeopleList()) {
System.out.println("Person ID: " + person.getId());
System.out.println(" Name: " + person.getName());
if (!person.getEmail().isEmpty()) {
System.out.println(" E-mail address: " + person.getEmail());
}
for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
switch (phoneNumber.getType()) {
case MOBILE:
System.out.print(" Mobile phone #: ");
break;
case HOME:
System.out.print(" Home phone #: ");
break;
case WORK:
System.out.print(" Work phone #: ");
break;
}
System.out.println(phoneNumber.getNumber());
}
}
}
public static void main(String[] args) throws Exception {
AddressBook addressBook =
AddressBook.parseFrom(new FileInputStream(args[0]));
Print(addressBook);
}
}
Cross-language compatibility
Because all language runtimes share the same binary wire format, you can write data with one language and read it with another. For example, the address book examples in the protobuf repository all use the same addressbook.data file:
# Write using Python
python add_person.py addressbook.data
# Read using Java
java -cp .:protobuf-java-4.35.0.jar ListPeople addressbook.data
Next steps
- Read the Installation guide to set up
protoc and your language runtime.
- Explore the full set of scalar types, nested messages, and field options in the proto3 language reference.