2016-03-17 4 views
0

Мне нужно использовать опубликованный (сторонний) протокол-буфер (.proto) файл, который содержит поле с именем из Java reserved keywords list. Поэтому я не могу изменить имена этого файла. В результате после компиляции (через protoc) буфер протокола в код Java. Я получаю класс, который не может быть скомпилирован с помощью Java.Как переименовать поле в сгенерированном Java-классе для предотвращения проблем с Java-компилятором

сообщение Я должен разобрать был сгенерирован с именем исходного поля (в недействительных в Java) с помощью C, например.

Как я понимаю, я не могу сгенерировать сгенерированный код без проблем при использовании этого сообщения/класса.

Как я могу изменить имя генерируемого поля (использовать некоторые правила отображения во время работы protoc или использовать аннотации) в сгенерированном Java класса безопасно?

Образец.

прото файл:

package sample.wrongname.protobuf; 

enum SomeType { 
    cool_name = 1; 
    another_cool_name = 2; 
    native = 3; 
} 

Сформирован Java класс:

public final class Sample { 
    private Sample() {} 
    public static void registerAllExtensions(
     com.google.protobuf.ExtensionRegistry registry) { 
    } 
    /** 
    * Protobuf enum {@code sample.wrongname.protobuf.SomeType} 
    */ 
    public enum SomeType 
     implements com.google.protobuf.ProtocolMessageEnum { 
    /** 
    * <code>cool_name = 1;</code> 
    */ 
    cool_name(0, 1), 
    /** 
    * <code>another_cool_name = 2;</code> 
    */ 
    another_cool_name(1, 2), 
    /** 
    * <code>native = 3;</code> 
    */ 
    native(2, 3), 
    ; 

    /** 
    * <code>cool_name = 1;</code> 
    */ 
    public static final int cool_name_VALUE = 1; 
    /** 
    * <code>another_cool_name = 2;</code> 
    */ 
    public static final int another_cool_name_VALUE = 2; 
    /** 
    * <code>native = 3;</code> 
    */ 
    public static final int native_VALUE = 3; 


    public final int getNumber() { return value; } 

    public static SomeType valueOf(int value) { 
     switch (value) { 
     case 1: return cool_name; 
     case 2: return another_cool_name; 
     case 3: return native; 
     default: return null; 
     } 
    } 

    public static com.google.protobuf.Internal.EnumLiteMap<SomeType> 
     internalGetValueMap() { 
     return internalValueMap; 
    } 
    private static com.google.protobuf.Internal.EnumLiteMap<SomeType> 
     internalValueMap = 
      new com.google.protobuf.Internal.EnumLiteMap<SomeType>() { 
      public SomeType findValueByNumber(int number) { 
       return SomeType.valueOf(number); 
      } 
      }; 

    public final com.google.protobuf.Descriptors.EnumValueDescriptor 
     getValueDescriptor() { 
     return getDescriptor().getValues().get(index); 
    } 
    public final com.google.protobuf.Descriptors.EnumDescriptor 
     getDescriptorForType() { 
     return getDescriptor(); 
    } 
    public static final com.google.protobuf.Descriptors.EnumDescriptor 
     getDescriptor() { 
     return Sample.getDescriptor().getEnumTypes().get(0); 
    } 

    private static final SomeType[] VALUES = values(); 

    public static SomeType valueOf(
     com.google.protobuf.Descriptors.EnumValueDescriptor desc) { 
     if (desc.getType() != getDescriptor()) { 
     throw new java.lang.IllegalArgumentException(
      "EnumValueDescriptor is not for this type."); 
     } 
     return VALUES[desc.getIndex()]; 
    } 

    private final int index; 
    private final int value; 

    private SomeType(int index, int value) { 
     this.index = index; 
     this.value = value; 
    } 

    // @@protoc_insertion_point(enum_scope:sample.wrongname.protobuf.SomeType) 
    } 


    public static com.google.protobuf.Descriptors.FileDescriptor 
     getDescriptor() { 
    return descriptor; 
    } 
    private static com.google.protobuf.Descriptors.FileDescriptor 
     descriptor; 
    static { 
    java.lang.String[] descriptorData = { 
     "\n\014sample.proto\022\031sample.wrongname.protobu" + 
     "f*<\n\010SomeType\022\r\n\tcool_name\020\001\022\025\n\021another_" + 
     "cool_name\020\002\022\n\n\006native\020\003" 
    }; 
    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = 
     new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { 
      public com.google.protobuf.ExtensionRegistry assignDescriptors(
       com.google.protobuf.Descriptors.FileDescriptor root) { 
      descriptor = root; 
      return null; 
      } 
     }; 
    com.google.protobuf.Descriptors.FileDescriptor 
     .internalBuildGeneratedFileFrom(descriptorData, 
     new com.google.protobuf.Descriptors.FileDescriptor[] { 
     }, assigner); 
    } 

    // @@protoc_insertion_point(outer_class_scope) 
} 
+0

Переименуйте 'native (2, 3)' в допустимое имя метода Java 'nativeFoo (2, 3)'. Пока вы не меняете структуру протобуфера, нет проблем. – SubOptimal

+0

Спасибо, я попробую.Является ли это общим решением для всех подобных случаев (например, для поля сообщения)? Как двигатель может найти поле в этом случае (имена будут разными: в классе и в прото-файле)? –

+0

Сообщение было сгенерировано с помощью * C * с именем поля 'native' –

ответ

3

Вот небольшой пример.

Протобуфер с использованием зарезервированного ключевого слова Java.

package wrong.name; 
option java_outer_classname = "WrongProtos"; 
message Foo { 
    required SomeType id = 1; 
} 
enum SomeType { 
    cool_name = 1; 
    another_cool_name = 2; 
    native = 3; 
} 

Протобуфер, использующий ту же структуру, что и другое название.

package right.name; 
option java_outer_classname = "RightProtos"; 
message Foo { 
    required SomeType id = 1; 
} 
enum SomeType { 
    cool_name = 1; 
    another_cool_name = 2; 
    different = 3; 
} 

скомпилировать protobuffer

protoc --java_out=src/ *.proto 

Rename в WrongProtos.java

native(2, 3) --> nativeFoo(2, 3) 
case 3: return native; --> case 3: return nativeFoo; 

Небольшой фрагмент кода, чтобы показать, что структура может быть прочитана с обеих protobuff определений.

WrongProtos.Foo.Builder outFoo = WrongProtos.Foo.newBuilder(); 
outFoo.setId(WrongProtos.SomeType.nativeFoo); 
try (FileOutputStream output = new FileOutputStream("/tmp/proto.bin")) { 
    outFoo.build().writeTo(output); 
} 
System.out.printf("outFoo number: %d name: %s%n", 
     outFoo.getId().getNumber(), outFoo.getId()); 

RightProtos.Foo inFoo = RightProtos.Foo.parseFrom(
     new FileInputStream("/tmp/proto.bin")); 
System.out.printf("inFoo number: %d name: %s%n", 
     inFoo.getId().getNumber(), inFoo.getId()); 
} 

выход

outFoo number: 3 name: nativeFoo 
inFoo number: 3 name: different 

Выходные данные показывают, что только в случае, если доступ к самому имя поля не было бы разницы. В двоичных данных имя поля не сохраняется.

Редактировать Другой способ может состоять в том, чтобы переименовать поле в верхний регистр native --> NATIVE.