Nested Types in Protocol Buffers
In this tutorial, you will learn about Nested Types in Protocol Buffers. We cover key concepts, practical examples, and best practices to help you master this topic.
Nested types in Protocol Buffers allow defining messages, enums, and oneofs inside other messages. This provides logical grouping, prevents name collisions, and communicates that the nested type belongs to its parent context.
What You'll Learn
- Defining nested messages, enums, and oneofs
- Accessing nested types from generated code
- Nesting depth best practices
- When to use nested vs top-level types
Why It Matters
Nested types keep the proto file organized and make the schema more readable. They signal ownership and scope. Too much nesting creates verbose generated code.
Real-World Use
Google's Api Design guidelines recommend nesting types that are only used as helper types within a parent message. The gRPC health.proto uses nested messages for request and response types.
flowchart LR
Message[Parent Message] --> NestedMsg[Nested Message]
Message --> NestedEnum[Nested Enum]
Message --> NestedOneof[Nested Oneof]
NestedMsg --> CodeMsg[Generated: Parent.NestedMsg]
NestedEnum --> CodeEnum[Generated: Parent.NestedEnum]
Teacher Mindset
Nest types when they exist only as helpers for the parent. Keep nesting at most two levels deep. If a type is used by multiple parent messages, make it top-level.
Code Examples
// Example 1: Multi-level nesting
message Library {
message Book {
string id = 1;
string title = 2;
string isbn = 3;
enum Genre {
GENRE_UNSPECIFIED = 0;
FICTION = 1;
NON_FICTION = 2;
SCIENCE = 3;
}
Genre genre = 4;
message Author {
string name = 1;
string bio = 2;
}
Author author = 5;
}
message Member {
string id = 1;
string name = 2;
}
string name = 1;
repeated Book books = 2;
repeated Member members = 3;
}
// Example 2: Nested oneof in message
message Payment {
string id = 1;
oneof method {
CreditCard card = 2;
PayPal paypal = 3;
Crypto crypto = 4;
}
message CreditCard {
string number = 1;
string expiry = 2;
string cvv = 3;
}
message PayPal {
string email = 1;
}
message Crypto {
string wallet_address = 1;
string currency = 2;
}
}
# Example 3: Accessing nested types in Python
from library_pb2 import Library
# Access nested messages
book = Library.Book()
book.title = "GraphQL in Action"
book.genre = Library.Book.Genre.FICTION
author = Library.Book.Author()
author.name = "John Doe"
book.author.CopyFrom(author)
library = Library()
library.name = "Central Library"
library.books.append(book)
Common Mistakes
- Nesting types three or more levels deep, making code verbose
- Defining a nested type that is used outside the parent message
- Using nested types when the parent message is already very large
- Forgetting to use the full path to access nested types in generated code
- Mixing nested and top-level types inconsistently within a project
Practice
- Create a School message with a nested Student message.
- Add a nested enum Grade to Student.
- Add a nested oneof Contact to Student for email or phone.
- Access the nested types in your language's generated code.
- Challenge: Design a Company message with deeply nested Department, Employee, and Project messages.
FAQ
Mini Project
Refactor your order management protos to use nested types. Put OrderItem inside Order, ShippingAddress inside Order, and PaymentMethod as a nested oneof inside Payment. Ensure all types are at most 2 levels deep.
What's Next
Next, you will learn about defining services in .proto files for gRPC endpoints.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro