2

我想验证生成的 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;
}

我想在代码中对 Currency 枚举进行一些验证,该代码由生成protobuf并丢弃错误消息,以防值不适用于提供的枚举(例如:)invalid currency。可能吗?

4

1 回答 1

2

您可以对其进行验证,但您也应该了解 Protobuf 枚举的细微差别。

  1. 始终UNKNOWN = 0;为每个枚举包含一个枚举值。当 Protobuf 不知道枚举值对应什么时,它会将其设置为默认值。这使您可以检测具有新代码的较新客户端何时使用服务器不理解的值。另外,如果该字段未设置,它自然等于UNKNOWNwhich 让您检查该字段是否不存在。(如果您确实想允许不存在的枚举,请将它们包装在 a 中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

此代码检查代码是否是受支持的代码之一。如果有不支持的代码进来,会由UNKNOWNcase处理,并提前返回错误。如果您修改了原型并添加了更多案例,静态分析将捕获丢失的案例(或抛出 AssertionError)。请注意,如果客户端更新他们的原型,这将不会发生。避免使用defaultcase,因为修改proto的时候很容易漏掉。或者,您可以将所有支持的案例放在地图中并检查它是否存在。

于 2019-06-06T21:57:39.497 回答