go-proto-validators

Generate message validators from .proto annotations.

Github星跟踪图

Golang ProtoBuf Validator Compiler

Travis Build
Apache 2.0 License

A protoc plugin that generates Validate() error functions on Go proto structs based on field options inside .proto
files. The validation functions are code-generated and thus don't suffer on performance from tag-based reflection on
deeply-nested messages.

Requirements

Using Protobuf validators is currently verified to work with:

It should still be possible to use it in project using earlier Go versions. However if you want to contribute to this
repository you'll need at least 1.11 for Go module support.

Paint me a code picture

Let's take the following proto3 snippet:

syntax = "proto3";
package validator.examples;
import "github.com/mwitkow/go-proto-validators/validator.proto";

message InnerMessage {
  // some_integer can only be in range (1, 100).
  int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
  // some_float can only be in range (0;1).
  double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
}

message OuterMessage {
  // important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax).
  string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
  // proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.
  InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];
}

First, the required keyword is back for proto3, under the guise of msg_exists. The painful if-nil checks are taken care of!

Second, the expected values in fields are now part of the contract .proto file. No more hunting down conditions in code!

Third, the generated code is understandable and has clear understandable error messages. Take a look:

func (this *InnerMessage) Validate() error {
	if !(this.SomeInteger > 0) {
		return fmt.Errorf("validation error: InnerMessage.SomeInteger must be greater than '0'")
	}
	if !(this.SomeInteger < 100) {
		return fmt.Errorf("validation error: InnerMessage.SomeInteger must be less than '100'")
	}
	if !(this.SomeFloat >= 0) {
		return fmt.Errorf("validation error: InnerMessage.SomeFloat must be greater than or equal to '0'")
	}
	if !(this.SomeFloat <= 1) {
		return fmt.Errorf("validation error: InnerMessage.SomeFloat must be less than or equal to '1'")
	}
	return nil
}

var _regex_OuterMessage_ImportantString = regexp.MustCompile("^[a-z]{2,5}$")

func (this *OuterMessage) Validate() error {
	if !_regex_OuterMessage_ImportantString.MatchString(this.ImportantString) {
		return fmt.Errorf("validation error: OuterMessage.ImportantString must conform to regex '^[a-z]{2,5}$'")
	}
	if nil == this.Inner {
		return fmt.Errorf("validation error: OuterMessage.Inner message must exist")
	}
	if this.Inner != nil {
		if err := validators.CallValidatorIfExists(this.Inner); err != nil {
			return err
		}
	}
	return nil
}

Installing and using

The protoc compiler expects to find plugins named proto-gen-XYZ on the execution $PATH. So first:

export PATH=${PATH}:${GOPATH}/bin

Then, do the usual

go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators

Your protoc builds probably look very simple like:

protoc  \
  --proto_path=. \
  --go_out=. \
  *.proto

That's fine, until you encounter .proto includes. Because go-proto-validators uses field options inside the .proto
files themselves, it's .proto definition (and the Google descriptor.proto itself) need to on the protoc include
path. Hence the above becomes:

protoc  \
  --proto_path=${GOPATH}/src \
  --proto_path=${GOPATH}/src/github.com/google/protobuf/src \
  --proto_path=. \
  --go_out=. \
  --govalidators_out=. \
  *.proto

Or with gogo protobufs:

protoc  \
  --proto_path=${GOPATH}/src \
  --proto_path=${GOPATH}/src/github.com/gogo/protobuf/protobuf \
  --proto_path=. \
  --gogo_out=. \
  --govalidators_out=gogoimport=true:. \
  *.proto

Basically the magical incantation (apart from includes) is the --govalidators_out. That triggers the
protoc-gen-govalidators plugin to generate mymessage.validator.pb.go. That's it :)

License

go-proto-validators is released under the Apache 2.0 license. See the LICENSE file for details.

主要指标

概览
名称与所有者mwitkow/go-proto-validators
主编程语言Go
编程语言Makefile (语言数: 4)
平台
许可证Apache License 2.0
所有者活动
创建于2016-03-27 17:16:21
推送于2023-10-25 03:15:36
最后一次提交2022-10-24 09:49:13
发布数5
最新版本名称v0.3.2 (发布于 2020-08-14 10:53:41)
第一版名称v0.1.0 (发布于 )
用户参与
星数1.1k
关注者数14
派生数164
提交数102
已启用问题?
问题数72
打开的问题数41
拉请求数32
打开的拉请求数6
关闭的拉请求数16
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?