Skip to content

Instantly share code, notes, and snippets.

@mwmitchell
Created August 24, 2021 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mwmitchell/e64d5cfde5d6917f0198302d1d2969d2 to your computer and use it in GitHub Desktop.
Save mwmitchell/e64d5cfde5d6917f0198302d1d2969d2 to your computer and use it in GitHub Desktop.
package foo.bar.proto;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
// Based on https://stackoverflow.com/a/49480375/3780523 + `mapToProto(...)`
public class ProtoUtil {
public static void mapToProto(Map<String, Object> map, Message.Builder builder) {
builder.getDescriptorForType().getFields().forEach(f -> {
if (map.containsKey(f.getName())) {
if (f.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
Message.Builder fBuilder = builder.newBuilderForField(f);
Object val = map.get(f.getName());
if (val instanceof Collection) {
System.out.println("ok -> " + val);
((Collection<?>) val).forEach(v -> {
mapToProto((Map<String, Object>) v, fBuilder);
builder.addRepeatedField(f, fBuilder.build());
});
} else {
mapToProto((Map<String, Object>) val, fBuilder);
builder.setField(f, fBuilder.build());
}
} else {
Object v = map.get(f.getName());
if (f.getType() == Descriptors.FieldDescriptor.Type.INT32) {
if (v instanceof Long) {
v = ((Long) v).intValue();
}
builder.setField(f, v);
} else {
builder.setField(f, v);
}
}
}
});
}
public static Map<String, Object> protoToMap(Message proto) {
final Map<Descriptors.FieldDescriptor, Object> allFields = proto.getAllFields();
Map<String, Object> map = new LinkedHashMap<>();
for (Map.Entry<Descriptors.FieldDescriptor, Object> entry : allFields.entrySet()) {
final Descriptors.FieldDescriptor fieldDescriptor = entry.getKey();
final Object requestVal = entry.getValue();
final Object mapVal = convertVal(proto, fieldDescriptor, requestVal);
if (mapVal != null) {
final String fieldName = fieldDescriptor.getName();
map.put(fieldName, mapVal);
}
}
return map;
}
static Object convertVal(Message proto, Descriptors.FieldDescriptor fieldDescriptor, Object protoVal) {
Object result = null;
if (protoVal != null) {
if (fieldDescriptor.isRepeated()) {
if (proto.getRepeatedFieldCount(fieldDescriptor) > 0) {
final List originals = (List) protoVal;
final List copies = new ArrayList(originals.size());
for (Object original : originals) {
copies.add(convertAtomicVal(fieldDescriptor, original));
}
result = copies;
}
} else {
result = convertAtomicVal(fieldDescriptor, protoVal);
}
}
return result;
}
static Object convertAtomicVal(Descriptors.FieldDescriptor fieldDescriptor, Object protoVal) {
Object result = null;
if (protoVal != null) {
switch (fieldDescriptor.getJavaType()) {
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case BOOLEAN:
case STRING:
result = protoVal;
break;
case BYTE_STRING:
case ENUM:
result = protoVal.toString();
break;
case MESSAGE:
result = protoToMap((Message) protoVal);
break;
}
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment