如何在生成的 Java class 中重命名字段以防止 Java 编译器出现问题
How to rename field in generated Java class to prevent problems with Java compiler
我必须使用已发布的(第 3 方)协议缓冲区 (.proto) 文件,其中包含名称来自 Java reserved keywords list 的字段。所以我无法更改此文件的名称。作为编译(通过 protoc)协议缓冲区到 Java 代码后的结果,我得到 class 可以不能用 Java 编译。
我必须解析的消息是在 C[=40 的帮助下使用原始字段名称生成的(在 Java 中无效) =],例如。
据我了解,在使用此 message/class 期间,我无法在不遇到麻烦的情况下更改生成的代码。
如何在生成的 [=51 中更改生成字段的名称(在 运行 protoc 期间使用一些映射规则或使用注释) =]class安全吗?
样本。
原型文件:
package sample.wrongname.protobuf;
enum SomeType {
cool_name = 1;
another_cool_name = 2;
native = 3;
}
生成Javaclass:
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 = {
"\n4sample.proto21sample.wrongname.protobu" +
"f*<\n0SomeType2\r\n\tcool_name0[=14=]125\n1another_" +
"cool_name0[=14=]22\n\n[=14=]6native0[=14=]3"
};
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)
}
这是一个小例子。
使用 Java 保留关键字的 Protobuffer。
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;
}
使用相同结构但名称不同的 Protobuffer。
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;
}
编译原型缓冲区
protoc --java_out=src/ *.proto
在 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
输出显示,只有在您访问字段名称本身时才会有所不同。在二进制数据中,不存储字段名称。
edit 另一种方法是将字段重命名为大写 native --> NATIVE
.
我必须使用已发布的(第 3 方)协议缓冲区 (.proto) 文件,其中包含名称来自 Java reserved keywords list 的字段。所以我无法更改此文件的名称。作为编译(通过 protoc)协议缓冲区到 Java 代码后的结果,我得到 class 可以不能用 Java 编译。
我必须解析的消息是在 C[=40 的帮助下使用原始字段名称生成的(在 Java 中无效) =],例如。
据我了解,在使用此 message/class 期间,我无法在不遇到麻烦的情况下更改生成的代码。
如何在生成的 [=51 中更改生成字段的名称(在 运行 protoc 期间使用一些映射规则或使用注释) =]class安全吗?
样本。
原型文件:
package sample.wrongname.protobuf;
enum SomeType {
cool_name = 1;
another_cool_name = 2;
native = 3;
}
生成Javaclass:
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 = {
"\n4sample.proto21sample.wrongname.protobu" +
"f*<\n0SomeType2\r\n\tcool_name0[=14=]125\n1another_" +
"cool_name0[=14=]22\n\n[=14=]6native0[=14=]3"
};
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)
}
这是一个小例子。
使用 Java 保留关键字的 Protobuffer。
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;
}
使用相同结构但名称不同的 Protobuffer。
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;
}
编译原型缓冲区
protoc --java_out=src/ *.proto
在 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
输出显示,只有在您访问字段名称本身时才会有所不同。在二进制数据中,不存储字段名称。
edit 另一种方法是将字段重命名为大写 native --> NATIVE
.