javaprotocol-buffers

Filling up a map field in Proto using reflection API


I am trying to write a module that will get a Message.Builder and a Map from field name to value and will fill the Builder with the values.

All works well until I encounter a map field ( using Proto3 ).

I get that for a specific message whose fields I know I can do:

builder.b.putAll<MapeFieldName>( map ),

But how do I use the Proto reflection API to achieve the same.

The MapEntry doc says: "In reflection API, map fields will be treated as repeated message fields and each map entry is accessed as a message." But I don't quite get what that means.


Solution

  • I have wasted some time on this and thought someone else might find it useful:

    When using the proto reflection API on map fields, you indeed treat the map field as a repeated field of com.google.protobuf.MapEntry:

    FieldDescriptor mapFieldDescriptor = protoDescriptor.findFieldByName( map_field_name );
    MapEntry.Builder entryBuilder = ( MapEntry.Builder ) topProtoBuilder.newBuilderForField( mapFieldDescriptor );
    

    then for each entry in my map:

    entryBuilder.setKey( e.getKey() );
    entryBuilder.setValue( e.getValue() );
    underlyingProtoBuilder.addRepeatedField( mapFieldDescriptor , entryBuilder.build() );
    

    The only thing that still bothers me is the MapEntry doc saying: "Users shouldn't use this class" when I had to explicitly use the MapEntry.Builder.

    Also I am not sure why protobuf doesn't let you simply builder.setField( mapFieldDescriptor , a java Map ) which seems much cleaner.