The protoschema-plugins repository contains a collection of Protobuf plugins that generate different types of schema from protobuf files. This includes:
Generates a schema for a given protobuf file that can be used as a PubSub schema in the form of a single self-contained messaged normalized to proto2.
Install the protoc-gen-pubsub
plugin directly:
go install github.com/bufbuild/protoschema-plugins/cmd/protoc-gen-pubsub@latest
Or reference it as a Remote Plugin in buf.gen.yaml
:
version: v1
plugins:
- plugin: buf.build/bufbuild/protoschema-pubsub
out: ./gen
For examples see testdata which contains the generated schema for test case definitions found in proto.
Generates a JSON Schema for a given protobuf file. This implementation uses the latest JSON Schema Draft 2020-12.
Install the protoc-gen-jsonschema
directly:
go install github.com/bufbuild/protoschema-plugins/cmd/protoc-gen-jsonschema@latest
Or reference it as a Remote Plugin in buf.gen.yaml
:
version: v1
plugins:
- plugin: buf.build/bufbuild/protoschema-jsonschema
out: ./gen
For examples see testdata which contains the generated schema for test case definitions found in proto.
Here is a simple generated schema from the following protobuf:
// A product.
//
// A product is a good or service that is offered for sale.
message Product {
// A point on the earth's surface.
message Location {
double lat = 1 [
(buf.validate.field).double.finite = true,
(buf.validate.field).double.gte = -90,
(buf.validate.field).double.lte = 90
];
double long = 2 [
(buf.validate.field).double.finite = true,
(buf.validate.field).double.gte = -180,
(buf.validate.field).double.lte = 180
];
}
// The unique identifier for the product.
int32 product_id = 1 [(buf.validate.field).required = true];
// The name of the product.
string product_name = 2 [(buf.validate.field).required = true];
// The price of the product.
float price = 3 [
(buf.validate.field).float.finite = true,
(buf.validate.field).float.gte = 0
];
// The tags associated with the product.
repeated string tags = 4;
// The location of the product.
Location location = 5 [(buf.validate.field).required = true];
}
Results in the following JSON Schema files:
*.schema.json
files are generated with underscore-case fields*.jsonschema.json
files are generated with camelCase
For example, the above protobuf generates the following *.schema.json
files:
Product.schema.json
{
"$id": "Product.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"title": "A product.",
"description": "A product is a good or service that is offered for sale.",
"type": "object",
"properties": {
"product_id": {
"description": "The unique identifier for the product.",
"maximum": 2147483647,
"minimum": -2147483648,
"type": "integer"
},
"product_name": {
"description": "The name of the product.",
"type": "string"
},
"price": {
"anyOf": [
{
"maximum": 3.4028234663852886e38,
"minimum": 0,
"type": "number"
},
{
"pattern": "^-?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$",
"type": "string"
}
],
"default": 0,
"description": "The price of the product."
},
"tags": {
"description": "The tags associated with the product.",
"items": {
"type": "string"
},
"type": "array"
},
"location": {
"$ref": "Product.Location.schema.json",
"description": "The location of the product."
}
},
"required": ["product_id", "product_name", "location"],
"patternProperties": {
"^(productId)$": {
"description": "The unique identifier for the product.",
"maximum": 2147483647,
"minimum": -2147483648,
"type": "integer"
},
"^(productName)$": {
"description": "The name of the product.",
"type": "string"
}
}
}
Product.Location.schema.json
{
"$id": "Location.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"title": "Location",
"description": "A point on the earth's surface.",
"type": "object",
"properties": {
"lat": {
"anyOf": [
{
"maximum": 90,
"minimum": -90,
"type": "number"
},
{
"pattern": "^-?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$",
"type": "string"
}
],
"default": 0
},
"long": {
"anyOf": [
{
"maximum": 180,
"minimum": -180,
"type": "number"
},
{
"pattern": "^-?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$",
"type": "string"
}
],
"default": 0
}
}
}
Or the following *.jsonschema.json
files, when the strict
option is set to true
:
Product.jsonschema.json
{
"$id": "Product.jsonschema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"title": "A product.",
"description": "A product is a good or service that is offered for sale.",
"type": "object",
"properties": {
"productId": {
"description": "The unique identifier for the product.",
"maximum": 2147483647,
"minimum": -2147483648,
"type": "integer"
},
"productName": {
"description": "The name of the product.",
"type": "string"
},
"price": {
"description": "The price of the product.",
"maximum": 3.4028234663852886e38,
"minimum": 0,
"type": "number"
},
"tags": {
"description": "The tags associated with the product.",
"items": {
"type": "string"
},
"type": "array"
},
"location": {
"$ref": "Product.Location.jsonschema.json",
"description": "The location of the product."
}
},
"required": ["productId", "productName", "price", "location"]
}
Product.Location.jsonschema.json
{
"$id": "buf.protoschema.test.v1.Product.Location.jsonschema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"title": "Location",
"description": "A point on the earth's surface.",
"type": "object",
"properties": {
"lat": {
"maximum": 90,
"minimum": -90,
"type": "number"
},
"long": {
"maximum": 180,
"minimum": -180,
"type": "number"
}
},
"required": ["lat", "long"]
}
The JSON Schema plugin supports the following options:
additional_properties
- Iftrue
, the generated schema will setadditionalProperties
totrue
, causing unknown fields to be ignored instead of erroring. Defaults tofalse
. Useful when a client/sender may have a newer schema (which may include new fields) than the server/receiver. Similar to the "ignore unknown fields" option in Protobuf JSON.strict
- Iftrue
, the generated schema will not allow aliases, string numbers, or any other non-normalized representation. Defaults tofalse
. Useful if the JSON being validated is used directly instead of being converted to a Protobuf message. Requires the "always emit fields without presence" option when using Protobuf JSON.
For help and discussion around Protobuf, best practices, and more, join us on Slack.
This project is currently in alpha. The API should be considered unstable and likely to change.
Offered under the Apache 2 license.