Home  >  Article  >  Backend Development  >  How to make a Protobuf 3 field required?

How to make a Protobuf 3 field required?

WBOY
WBOYforward
2024-02-09 08:10:28655browse

如何使 Protobuf 3 字段成为必填字段?

Protobuf 3 is an efficient data serialization format, but during use, sometimes you need to make certain fields required. So, how do you make a Protobuf 3 field required? In this article, PHP editor Strawberry will introduce you in detail how to use the features of Protobuf 3 to implement required fields, and provide corresponding code examples. Whether you are a beginner or an experienced developer, this article can help you quickly master the use of required fields and improve the robustness and reliability of your code. Let’s take a look!

Question content

I am writing my first api endpoint in golang using grpc/proto-buffers. I'm pretty new to go. Below is the file I wrote for the test case

package my_package

import (
    "context"
    "testing"

    "github.com/stretchr/testify/require"

    "google.golang.org/protobuf/types/known/structpb"
    "github.com/myteam/myproject/cmd/eventstream/setup"
    v1handler "github.com/myteam/myproject/internal/handlers/myproject/v1"
    v1interface "github.com/myteam/myproject/proto/.gen/go/myteam/myproject/v1"
)

func testendpoint(t *testing.t) {
    conf := &setup.config{}

    // initialize our api handlers
    myhandler := v1handler.new(&v1handler.config{})

    t.run("success", func(t *testing.t) {
        res, err := myhandler.endpoint(context.background(), &v1interface.endpointrequest{
            a: "s",
            b: &structpb.struct{
                fields: map[string]*structpb.value{
                    "t": &structpb.value{
                        kind: &structpb.value_stringvalue{
                            stringvalue: "u",
                        },
                    },
                    "v": &structpb.value{
                        kind: &structpb.value_stringvalue{
                            stringvalue: "w",
                        },
                    },
                },
            },
            c: &timestamppb.timestamp{seconds: 1590179525, nanos: 0},
        })
        require.nil(t, err)

        // assert we got what we want.
        require.equal(t, "ok", res.text)
    })


}

This is how the endpointrequest object is defined in the v1.go file included above:

// An v1 interface Endpoint Request object.
message EndpointRequest {

  // a is something.
  string a = 1 [(validate.rules).string.min_len = 1];

  // b can be a complex object.
  google.protobuf.Struct b = 2;

  // c is a timestamp.
  google.protobuf.Timestamp c = 3;

}

The above test case seems to work fine.

I set up the validation rule to effectively make the parameter a a mandatory parameter, since it requires a to be a string containing at least 1. Therefore, if a is omitted, the endpoint will return 400.

But now I want to make sure that if the c or b endpoint is omitted a 400 is returned. How can I do this? In protobufs 3, they removed the required keyword. So how do I check if a non-string parameter is passed in and react accordingly?

Solution

The short version: You can't.

required was removed primarily because it made the change backwards incompatible. Trying to reimplement it with validation options isn't that drastic (changes are easier), but suffers from the drawbacks as you can see.

Instead, keep validation outside the prototype definition and move it into the application itself. Whenever you receive a message, you should check its contents (the same goes for when required appears). In rare cases, simple validation provided by options or required is sufficient.

The above is the detailed content of How to make a Protobuf 3 field required?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete