Skip to content

How to implement field validation for optional parameter #1256

Closed
@eldad87

Description

@eldad87

Hi,
I'm trying to implement a request with optional (omit) parameters with validation constrains.
As far as I understand, optional field can be achieved using oneof.
In addition, protoc-gen-validate supports oneof.

Unfortunately, when using oneof, the swagger definition and grpc-ecosystem are changed and I can't use the original field name.

Given the following proto:

syntax = "proto3";
package pb;

import "google/api/annotations.proto";
import "github.com/envoyproxy/protoc-gen-validate/validate/validate.proto";

service Account {
    rpc Update(UpdateRequest) returns (UpdateResponse) {
        option (google.api.http) = {
          put: "/v1/account/{ID}"
          body: "*"
        };
    }
}

message ID {
    uint32 ID = 1 [(validate.rules).uint32.gte = 0];
};

message UpdateRequest {
    int32 ID = 1;
    string FirstName = 2 [(validate.rules).string.min_len = 2];
    oneof LastName {
        bool LastNameNull = 3;
        string LastNameValue = 4 [(validate.rules).string.min_len = 2];
    }
}

message UpdateResponse {
    int32 ID = 1;
    string FirstName = 2;
    string LastName = 3;
}
  1. Whenever there is a oneof in the protobuf definition all the keys are simply added to the object: LastNameNull & LastNameValue. In other words, My request payload should contain LastNameValue instead of simply LastName.
    Keep in mind that my Request struct fields should have the same naming as my DB struct for marshaling purposes, therefore the following will not work for me As it adds LastNameValue isUpdateRequest_LastNameValue to the generated struct:
    oneof LastNameValue {
        bool LastNameNull = 3;
        string LastName = 4 [(validate.rules).string.min_len = 2];
    }
  1. If I try to send a request with FirstName defined, I get the following error json: cannot unmarshal string into Go value of type pb.isUpdateRequest_LastName.
    According to @ivucica's comment I should implement UnmarshalJSONPB for that object. Unfortunately pb.isUpdateRequest_LastName is an interface and therefore his suggestion is not applicable.

  2. What is your approach to unified DB & API validation errors?
    I have 2 validation levels. gRPC request level (max length etc) and DB objects (email already exists, etc) which can result in different naming convention, especially when nested structs are involved.
    I'm using the following interceptors to try and minimaize the situation by maintaining the same error structure.
    But still, I'm using different structs and therefore there will be different Naming in the error message & field name.

Please advise how to handle this situation,
Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions