I want to create .proto file through java code. I am able to do it with message having primitive type attributes as follow :
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();
}
Now my proto structure is
message Person{
optional string FName=1;
optional string LName=2;
optional string Status=3;}
And I can achieve this by using above methods.
I want to achieve:
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;}
Queries:
- How to add Address under Person(can try method addRepeatedField but couldn't create FileDescriptor)
- How to add Address as repeated field(ArrayList) under Person
Please give me any hint if anybody has.