Nested protocol buffers with reflection

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, you still need to set the a field using only the string "bar.a"? Ideally, I would like to write a method like the one 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 general way?

I also need to go the other way

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 great if the Field field does not contain a separator (".") And refers to a base message, but not a message attachment.

+4
source share
1 answer

You need to split the field path into. and perform a search chain, for example.

Message subMessage =
    (Message)message.getField(
        message.getDescriptorForType().findFieldByName("bar"));
return subMessage.getField(
    subMessage.getDescriptorForType().findFieldByName("a"));

Or 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());

, , ( ).

+4

All Articles