是否可以检查原型文件中的枚举值?

Is it possible to check enum value in proto file?

我想验证生成的 Java 代码中的枚举值。我有以下原型文件:

syntax = "proto3";

import "google/protobuf/empty.proto";

option java_multiple_files = true;
option java_package = "com.package";

package helloworld;

service SomeService {
    rpc DoAction (Request) returns (google.protobuf.Empty) { }
}

enum Currency {
    EUR = 0;
    GBP = 1;
    USD = 2;
}

message Request {
    string id = 1;
    Currency currency = 2;
}

我想对 protobuf 生成的代码中的货币枚举进行一些验证,并删除错误消息以防值不适用于提供的枚举(例如:invalid currency) .可能吗?

你可以验证它,但你也应该意识到 Protobuf 枚举的细微差别。

  1. 始终为每个枚举包含一个 UNKNOWN = 0; 枚举值。当 Protobuf 不知道枚举值对应的是什么时,它会将其设置为默认值。这使您可以检测到具有新代码的较新客户端何时使用服务器无法理解的值。此外,如果该字段未设置,它自然等于 UNKNOWN 让您检查该字段是否不存在。 (如果您确实希望允许缺少枚举,请将它们包装在 message{} 中)。

  2. 在您的服务器应用程序处理程序中,您应该检查客户端提供的支持值中的哪一个。如果它不是其中之一,您应该使用 INVALID_ARGUMENT 状态代码使 RPC 失败:

    out: {
      switch (req.getCurrency()) {
        case EUR: 
        case GBP:
        case USD: break out;
        case UNKNOWN:
          responseObserver.onError(
              Status.INVALID_ARGUMENT
                  .withDescription("bad currency " + req.getCurrency())
                  .asRuntimeException());
          return;
      }
      throw new AssertionError("missed case!");
    }
    // keep handling the request

此代码检查该代码是否是受支持的代码之一。如果出现不受支持的代码,它将由 UNKNOWN 情况处理,并且 return 会提前出错。如果您修改原型并添加更多案例,静态分析将捕获丢失的案例(或抛出 AssertionError)。请注意,如果客户端更新其原型,则 不会 发生。避免使用 default 大小写,因为在修改 proto 时很容易漏掉。或者,您可以将所有支持的案例放在地图中并检查它是否存在。