Enums#
This page documents why Protovalidate uses enums
and describes those provided by the Protovalidate API.
Background#
Protovalidate uses enums
when the value of a field should be one of a small set of valid values. For example, whether to ignore a field's validation rules often isn't a simple boolean decision: what if you only want to ignore validation when the field isn't populated, or if it's populated and its value is the default value?
By providing an Ignore
enum with values like IGNORE_IF_UNPOPULATED
, IGNORE_IF_DEFAULT_VALUE
, and IGNORE_ALWAYS
, Protovalidate lets you express your semantic requirements in easy-to-read code:
syntax="proto3";
message Request {
string uri = 1 [
// If no value is provided, skip validation.
(buf.validate.field).ignore = IGNORE_IF_UNPOPULATED,
(buf.validate.field).string.uri = true
];
}
Ignore#
Specifies how FieldRules.ignore
behaves, depending on the field's value, and
whether the field tracks presence.
IGNORE_UNSPECIFIED#
Ignore rules if the field tracks presence and is unset. This is the default behavior.
In proto3, only message fields, members of a Protobuf oneof
, and fields
with the optional
label track presence. Consequently, the following fields
are always validated, whether a value is set or not:
syntax="proto3";
message RulesApply {
string email = 1 [
(buf.validate.field).string.email = true
];
int32 age = 2 [
(buf.validate.field).int32.gt = 0
];
repeated string labels = 3 [
(buf.validate.field).repeated.min_items = 1
];
}
In contrast, the following fields track presence, and are only validated if a value is set:
syntax="proto3";
message RulesApplyIfSet {
optional string email = 1 [
(buf.validate.field).string.email = true
];
oneof ref {
string reference = 2 [
(buf.validate.field).string.uuid = true
];
string name = 3 [
(buf.validate.field).string.min_len = 4
];
}
SomeMessage msg = 4 [
(buf.validate.field).cel = {/* ... */}
];
}
To ensure that such a field is set, add the required
rule.
To learn which fields track presence, see the Field Presence cheat sheet.
IGNORE_IF_UNPOPULATED#
Ignore rules if the field is unset, also for fields that don't track presence.
In proto3, repeated fields, map fields, and fields with scalar types don't track presence. Consequently, the following fields are only validated if they are set:
syntax="proto3";
message RulesApplyIfSet {
// `string.email` is ignored for the empty string.
string link = 1 [
(buf.validate.field).string.email = true,
(buf.validate.field).ignore = IGNORE_IF_UNPOPULATED
];
// `int32.gte` is ignored for the zero value.
int32 age = 2 [
(buf.validate.field).int32.gte = 21,
(buf.validate.field).ignore = IGNORE_IF_UNPOPULATED
];
// `repeated.min_items` is ignored if the list is empty.
repeated string labels = 3 [
(buf.validate.field).repeated.min_items = 3,
(buf.validate.field).ignore = IGNORE_IF_UNPOPULATED
];
}
For fields that don't track presence, the field's value determines whether the field is set and rules apply:
- For string and bytes, an empty value is ignored.
- For bool, false is ignored.
- For numeric types, zero is ignored.
- For enums, the first defined enum value is ignored.
- For repeated fields, an empty list is ignored.
- For map fields, an empty map is ignored.
- For message fields, absence of the message (typically a null-value) is ignored.
For fields that track presence (e.g. adding the optional
label in proto3),
behavior is the same as the default IGNORE_UNSPECIFIED
.
To learn which fields track presence, see the Field Presence cheat sheet.
IGNORE_IF_DEFAULT_VALUE#
Ignore rules if the field is unset, or set to the default value.
The default value depends on the field type:
- For strings, the default value is the empty string.
- For bytes, the default value is empty bytes.
- For bool, the default value is false.
- For numeric types, the default value is zero.
- For enums, the default value is the first defined enum value.
- For repeated fields, the default is an empty list.
- For map fields, the default is an empty map.
- For message fields, Protovalidate treats the empty message as the default value. All rules of the referenced message are ignored as well.
For some fields, the default value can be overridden with the Protobuf
default
option.
For fields that don't track presence and don't have the default
option,
behavior is the same as the default IGNORE_UNSPECIFIED
.
IGNORE_ALWAYS#
Always ignore rules, including the required
rule.
This is useful for ignoring the rules of a referenced message, or to temporarily ignore rules during development.
message MyMessage {
// The field's rules will always be ignored, including any validation's
// on value's fields.
MyOtherMessage value = 1 [
(buf.validate.field).ignore = IGNORE_ALWAYS];
}
KnownRegex#
KnownRegex contains some well-known patterns.
KNOWN_REGEX_HTTP_HEADER_NAME#
HTTP header name as defined by RFC 7230.
KNOWN_REGEX_HTTP_HEADER_VALUE#
HTTP header value as defined by RFC 7230.