【问题标题】:Replace String Enum with protobuf auto generated Enum将字符串枚举替换为 protobuf 自动生成的枚举
【发布时间】:2013-10-08 07:24:04
【问题描述】:

我的 Enum 原始 java 代码是:

public enum CarModel {
    NOMODEL("NOMODEL");
    X("X"),
    XS("XS"),
    XSI("XS-I"); //NOTE the special - character. Can't be declared XS-I
    XSI2("XS-I.2"); //NOTE the special . character. Can't be declared XS-I.2
    private final String carModel;
    CarModel(String carModel) { 
        this.carModel = carModel;
    }

    public String getCarModel() { return carModel; }

    public static CarModel fromString(String text) {
        if (text != null) {
            for (CarModel c : CarModel.values()) {
                if (text.equals(c.carModel)) {
                    return c;
                }
            }
        }
        return NOMODEL; //default
    }
}

现在,如果我使用 protobuf,我会进入 .proto 文件:

enum CarModel {
    NOMODEL = 0;
    X = 1;
    XS = 2;
    XSI = 3;
    XSI2 = 4;
}

从我的earlier question 我知道我可以调用由 protoc 生成的枚举并删除我自己的类(从而避免重复的值定义),但我仍然需要在某个地方定义(在包装类中?包装类枚举类?)备用fromString() 方法将根据枚举返回正确的字符串。我该怎么做?

编辑: 如何实现以下内容:

String carModel = CarModel.XSI.toString(); 这将返回“XS-I”

和:

CarModel carModel = CarModel.fromString("XS-I.2");

【问题讨论】:

    标签: java string enums protocol-buffers


    【解决方案1】:

    您可以使用 Protobuf 的 "custom options" 来完成此操作。

    import "google/protobuf/descriptor.proto";
    
    option java_outer_classname = "MyProto";
    // By default, the "outer classname" is based on the proto file name.
    // I'm declaring it explicitly here because I use it in the example
    // code below.  Note that even if you use the java_multiple_files
    // option, you will need to use the outer classname in order to
    // reference the extension since it is not declared in a class.
    
    extend google.protobuf.EnumValueOptions {
      optional string car_name = 50000;
      // Be sure to read the docs about choosing the number here.
    }
    
    enum CarModel {
      NOMODEL = 0 [(car_name) = "NOMODEL"];
      X = 1 [(car_name) = "X"];
      XS = 2 [(car_name) = "XS"];
      XSI = 3 [(car_name) = "XS-I"];
      XSI2 = 4 [(car_name) = "XS-I.2"];
    }
    

    现在在 Java 中你可以这样做:

    String name =
        CarModel.XSI.getValueDescriptor()
        .getOptions().getExtension(MyProto.carName);
    assert name.equals("XS-I");
    

    https://developers.google.com/protocol-buffers/docs/proto#options(稍微向下滚动到自定义选项部分。)

    【讨论】:

    • 我已经尝试过您的代码,但似乎 protoc 没有创建我需要调用的 getProto() 方法,以便将 ValueDescriptor 转换为 Extension。有什么想法吗?
    • 还有一件事 - 在查看生成的 java 代码时,“XS-I”和“XS-I.2”字符串出现的唯一位置是在定义为的最后一个字段中:“ static {java.lang.String[] descriptorData = {" 并且基本上保存了我的 .proto 源
    • 糟糕,抱歉,该方法称为toProto,而不是getProto。我会编辑我的答案。是的,注释都进入了descriptorData。我给出的代码实际上是把它们从那里取出来的。
    • toProto 确实存在,但仍然没有 getExtension... 有什么想法吗?
    • 抱歉,我忘记了扩展挂起选项原型,而不是描述符原型。所以我猜你需要getOptions() 而不是toProto()。再次更新示例。
    【解决方案2】:
    CarModel carmodel =  Enum.valueOf(CarModel.class, "XS")
    

    CarModel carmodel =  CarModel.valueOf("XS");
    

    【讨论】:

    • 我需要另一个方向:String model = CarModel.XSI.toString();但是能够告诉它 XSI 翻译为“XS-I”。还有下面的 CarModel carModel = CarModel.fromString("XS-I");
    猜你喜欢
    • 2019-10-03
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    相关资源
    最近更新 更多