Say I have a Message in a .proto file with the following contents
Message Foo {
Message Bar {
optional int32 a = 1;
optional int32 b = 2;
}
optional Bar bar = 1;
}
In Java, is there anyway to set the field a using only the string "bar.a"? Ideally I'd like to write a method like below:
public Foo.Builder apply(Foo.Builder builder, String fieldPath, Object value) {
// fieldPath == "bar.a"
// This doesn't work
FieldDescriptor fd = builder.getDefaultInstanceForType().findFieldByName(fieldPath);
builder = builder.setField(fd, value);
}
But when I do this, I get an IllegalArgumentException.
Does anyone know how to do this in a generic fashion?
I also need to go the other way as well
public Object getValue(Foo message, String fieldPath) {
// This doesn't work
FieldDescriptor fd = message.getDefaultInstanceForType().findFieldByName(fieldPath);
return message.getField(fieldPath);
}
As a note, this works fine if the fieldPath does not contain a separator (".") and references a base Message, but not a nested Message.
You need to split the field path on '.' and do a chain of lookups, e.g.
Message subMessage =
(Message)message.getField(
message.getDescriptorForType().findFieldByName("bar"));
return subMessage.getField(
subMessage.getDescriptorForType().findFieldByName("a"));
Or to write:
FieldDescriptor desc = message.getDescriptorForType().findFieldByName("bar");
Message.Builder subBuilder = (Message.Builder)builder.getFieldBuilder(desc);
subBuilder.setField(
subMessage.getDescriptorForType().findFieldByName("a"), value);
builder.setField(desc, subBuilder.build());
You could of course write a library that splits the string and does all the lookups in one call (and do proper error checking).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With