protoc-gen-pydantic
is a protoc
plugin that automatically generates Pydantic model definitions from .proto
files. This tool is designed to help developers seamlessly integrate protobuf-defined models with Pydantic, a powerful data validation and settings management library for Python.
- Supports all standard
proto3
field types. - Handles nested messages and enums.
- Generates Pydantic models with type annotations and field descriptions.
- Supports
oneof
,optional
,repeated
, andmap
fields. - Retains comments from
.proto
files as docstrings in the generated models.
You can download the binaries from GitHub Releases.
You first need to have Go installed. If you don't have Go installed, you can download it from the Go downloads page.
Clone the repository and build the plugin:
git clone https://github.com/ornew/protoc-gen-pydantic
cd protoc-gen-pydantic
go build -o protoc-gen-pydantic main.go
To generate Pydantic model definitions, use protoc
with your .proto
files specifying --pydantic_out
:
protoc --plugin=protoc-gen-pydantic=./protoc-gen-pydantic \
--pydantic_out=./gen \
--proto_path=./proto_files \
./api/example.proto
If you use buf:
# buf.gen.yaml
version: v2
plugins:
- local: protoc-gen-pydantic
opt:
- paths=source_relative
out: gen
inputs:
- directory: api
buf config init
buf generate
Given a simple .proto
file:
syntax = "proto3";
package example;
// User model representing the example.User message.
message User {
string name = 1;
int32 age = 2;
repeated string emails = 3;
bool is_active = 4;
}
Running protoc
will generate a Pydantic model like this:
from enum import Enum as _Enum
from typing import Optional as _Optional
from pydantic import BaseModel as _BaseModel, Field as _Field
class User(_BaseModel):
"""
User model representing the example.User message.
"""
name: str = _Field(...)
age: int = _Field(...)
emails: list[str] = _Field(...)
is_active: bool = _Field(...)
option | description |
---|---|
preserving_proto_field_name |
Use the proto field naming for the output field name. If false , it will be in caml-case according to protojson rules. Default to false . |
auto_trim_enum_prefix |
Automatically remove prefixes from enum fields. Default to true |
use_integers_for_enums |
Use integers for enum values instead of enum names. Default to false . |
enum Status {
STATUS_UNSPECIFIED = 0;
STATUS_OK = 1;
STATUS_ERROR = 2;
}
If auto_trim_enum_prefix
is false
:
class Status(str, _Enum):
STATUS_UNSPECIFIED = "UNSPECIFIED"
STATUS_OK = "OK"
STATUS_ERROR = "ERROR"
If auto_trim_enum_prefix
is true
(default):
class Status(str, _Enum):
UNSPECIFIED = "UNSPECIFIED"
OK = "OK"
ERROR = "ERROR"
If use_integers_for_enums
is false
:
class Status(str, _Enum):
UNSPECIFIED = "UNSPECIFIED"
OK = "OK"
ERROR = "ERROR"
If use_integers_for_enums
is true
:
class Status(int, _Enum):
UNSPECIFIED = 0
OK = 1
ERROR = 2
Contributions are welcome! Please open an issue or submit a pull request with your changes.
This project is licensed under the Apache License 2.0. See LICENSE for more details.
If you have any questions, feel free to reach out to the author:
- Name: Arata Furukawa
- Email: old.river.new@gmail.com