Created
August 24, 2021 18:54
-
-
Save mwmitchell/e64d5cfde5d6917f0198302d1d2969d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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