我想通过java代码创建.proto文件。我可以使用具有原始类型属性的消息来执行此操作:
public void testDynamicProto() throws Exception {
byte[] bytes = buildPersonProtoDesc();
byte[] personBytes = buildPersonProto(bytes);
Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor
.buildFrom(
DescriptorProtos.FileDescriptorProto.parseFrom(bytes),
new Descriptors.FileDescriptor[0]);
Descriptors.Descriptor personDesc = fileDescriptor
.findMessageTypeByName(PERSON_MESSAGE);
DynamicMessage message = DynamicMessage.parseFrom(personDesc,
personBytes);
for (Map.Entry<Descriptors.FieldDescriptor, Object> entry : message
.getAllFields().entrySet()) {
// TODO: add asserts
System.out.println(entry.getKey().getName() + "------------"
+ entry.getValue());
}
// TODO: test repeated field
// TODO: test non destructive updates (addition of column) to person proto and make sure old protos can be parsed
}
private byte[] buildPersonProto(byte[] bytes)
throws Descriptors.DescriptorValidationException,
InvalidProtocolBufferException {
Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor
.buildFrom(
DescriptorProtos.FileDescriptorProto.parseFrom(bytes),
new Descriptors.FileDescriptor[0]);
Descriptors.Descriptor personDesc = fileDescriptor
.findMessageTypeByName(PERSON_MESSAGE);
DynamicMessage.Builder personBuilder = DynamicMessage
.newBuilder(personDesc);
personBuilder.setField(personDesc.findFieldByName(FNAME_FIELD), "Jon");
personBuilder.setField(personDesc.findFieldByName(LNAME_FIELD), "Doe");
personBuilder.setField(personDesc.findFieldByName(STATUS_FIELD), 2);
return personBuilder.build().toByteArray();
}
private byte[] buildPersonProtoDesc() {
DescriptorProtos.FileDescriptorProto.Builder fileDescriptorProtoBuilder = DescriptorProtos.FileDescriptorProto
.newBuilder();
DescriptorProtos.DescriptorProto.Builder messageProtoBuilderA = DescriptorProtos.DescriptorProto
.newBuilder();
messageProtoBuilderA.setName(PERSON_MESSAGE);
messageProtoBuilderA
.addFieldBuilder()
.setName(FNAME_FIELD)
.setNumber(1)
.setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_STRING);
messageProtoBuilderA
.addFieldBuilder()
.setName(LNAME_FIELD)
.setNumber(2)
.setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_STRING);
messageProtoBuilderA.addFieldBuilder().setName(STATUS_FIELD)
.setNumber(3)
.setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_INT32);
fileDescriptorProtoBuilder.addMessageType(messageProtoBuilderA);
DescriptorProtos.FileDescriptorProto fileDescriptorProto = fileDescriptorProtoBuilder
.build();
return fileDescriptorProto.toByteArray();
}
现在我的原型结构是
message Person{
optional string FName=1;
optional string LName=2;
optional string Status=3;}
我可以通过使用上述方法来实现这一目标。
我想实现:
message Person{
optional string FName=1;
optional string LName=2;
optional string Status=3;
message Address {
optional string country=1;
optional string state=2;
optional string city=3;}
repeated Address address=4;}
查询:
如果有人的话,请给我任何暗示。
答案 0 :(得分:0)
在Person
addNestedType()
上messageProtoBuilderA
调用DescriptorProto.Builder
下添加类型。 addNestedType()的输入是Address
的DescriptorProto,其构造方式与Person
的方式相同。
将address
字段添加到人员类型时,请在相应的setLabel(Label.LABEL_REPEATED)
上调用FieldDescriptorProto.Builder
。
DescriptorProto.Builder messageProtoBuilderA = ...;
messageProtoBuilderA.addNestedType(createAddressType());
FieldDescriptorProto.Builder addressField = FieldDescriptorProto.newBuilder();
addressField.setName("address")
.setLabel(Label.LABEL_REPEATED)
.setNumber(4)
.setType(Type.TYPE_MESSAGE)
.setTypeName("Address");
messageProtoBuilderA.addField(addressField);
...
private DescriptorProto.Builder createAddressType() {
DescriptorProto.Builder addressProtoBuilder = DescriptorProto.newBuilder();
addressProtoBuilder.setName("Address");
// add fields
return addressProtoBuilder;
}
答案 1 :(得分:0)
我相信所有的领域必须在一起。所以它应该是
optional string FName=1;
optional string LName=2;
optional string Status=3;
repeated Address address=4;
你可以把它放在你的Address定义下,这样代码就已经生成了。