protovalidate icon indicating copy to clipboard operation
protovalidate copied to clipboard

[Feature Request] Add skipped_fields field constraint for finer-grained skipped behavior

Open rodaine opened this issue 2 years ago • 4 comments

Feature description:

Today, we support the skipped standard constraint on message fields to skip any validation constraints applied to the underlying type. This is currently an all or nothing scenario, when perhaps it's desired to opt-out of one or a few of the message's fields.

Potentially, we can support this via a skipped_fields constraint which takes a FieldMask and can specify which not to evaluate.

Problem it solves or use case:

Example use-case where a message describing a resource elided a constraint for a field and had the RPC request object use a CEL expression to validate that nested field.

Proposed implementation or solution:

# validate.proto

# <snip>

message FieldConstraints {
  # <snip>
  oneof skip {
    bool skipped = 24;
    google.protobuf.FieldMask skipped_fields = XX;
  }
  # <snip>
}

# <snip>
# example.proto

message Foo {
  string id   = 1 [(buf.validate.field).string.uuid = true];
  bytes  data = 2 [(buf.validate.field).bytes.min_len = 42];
}

message Bar {
  Foo foo = 1 [(buf.validate.field).skipped_fields.paths = "id" ];
}

In the example above, Foo by itself will verify the value of the id field to be a UUID and the data field to be of a minimum length. However, if validate is called on a Bar containing a Foo, only the data field will be evaluated as id has been skipped.

rodaine avatar Oct 17 '23 17:10 rodaine

This will work for Google AIP update methods, where the input message is typically just a partial message, and unset values should not trigger validation if not specified in FieldMask update_mask.

The only drawback is that the update_mask is dynamic and must be applied in runtime via a reflection. For that reason, it would be handy to have MessageConstraints to set skipped_fields on the target message, not on its parent. Maybe define a new well-known function for skipping validation that could be used in the MessageConstraints.cel?

czabaj avatar Mar 03 '25 09:03 czabaj

This will work for Google AIP update methods, where the input message is typically just a partial message, and unset values should not trigger validation if not specified in FieldMask update_mask.

The only drawback is that the update_mask is dynamic and must be applied in runtime via a reflection. For that reason, it would be handy to have MessageConstraints to set skipped_fields on the target message, not on its parent. Maybe define a new well-known function for skipping validation that could be used in the MessageConstraints.cel?

This is essential for building an API that conforms to Google's AIP spec.

smthpickboy avatar May 17 '25 10:05 smthpickboy

¿Is there a workaround to implement dynamic validation given an update_mask? As @smthpickboy said, it is required for complying with Google's AIP

juanmarin-co avatar Jul 23 '25 21:07 juanmarin-co

This will work for Google AIP update methods, where the input message is typically just a partial message, and unset values should not trigger validation if not specified in FieldMask update_mask.

The only drawback is that the update_mask is dynamic and must be applied in runtime via a reflection. For that reason, it would be handy to have MessageConstraints to set skipped_fields on the target message, not on its parent. Maybe define a new well-known function for skipping validation that could be used in the MessageConstraints.cel?

Agreed. We need a way to validate only the fields specified in google.protobuf.FieldMask update_mask.

cyberxnomad avatar Sep 02 '25 04:09 cyberxnomad