写一下大致的思路,就是根据map中的key去匹配Message中的field,如果有就根据类型去赋值。 有需要的可以参考下这个思路。
public static void main(String[] args) throws IOException {
Map<String, String> value = new HashedMap();
value.put("int_value","11");
value.put("enum_value","1");
value.put("rep_int_value","22");
value.put("map","1:2");
value.put("message","{inner_string_value=abc}");
EventOuterClass.Event.Builder eventBuilder = EventOuterClass.Event.newBuilder();
System.out.println(buildMessage(eventBuilder, value));
}
// build MessageType
private static Object buildMessage(Message.Builder eventBuilder, Map<String, String> value){
Descriptors.Descriptor eventDesc = eventBuilder.getDescriptorForType();
for (Map.Entry<String, String> entry : value.entrySet()) {
final String fieldName = entry.getKey();
final String fieldValue = entry.getValue();
final Descriptors.FieldDescriptor fieldDesc = eventDesc.findFieldByName(fieldName);
if (fieldDesc != null) {
if (fieldDesc.isMapField()){
buildMapType(eventBuilder, fieldDesc, fieldValue);
}else if (fieldDesc.isRepeated()) {
if (Descriptors.FieldDescriptor.JavaType.MESSAGE.equals(fieldDesc.getJavaType())){
final Message.Builder subBuilder = eventBuilder.newBuilderForField(fieldDesc);
Map<String, String> subValue=null;//TODO fileldValue converted to map
eventBuilder.addRepeatedField(fieldDesc, buildMessage(subBuilder, subValue));
}else {
eventBuilder.addRepeatedField(fieldDesc, buildValue(fieldDesc, fieldValue));
}
} else {
if (Descriptors.FieldDescriptor.JavaType.MESSAGE.equals(fieldDesc.getJavaType())){
final Message.Builder subBuilder = eventBuilder.newBuilderForField(fieldDesc);
Map<String, String> subValue=null;//TODO fileldValue converted to map
eventBuilder.setField(fieldDesc, buildMessage(subBuilder, subValue));
}else {
eventBuilder.setField(fieldDesc, buildValue(fieldDesc, fieldValue));
}
}
}
}
return eventBuilder.build();
}
private static void buildMapType(Message.Builder currentBuilder, Descriptors.FieldDescriptor field, String realVal) {
//split by :
final String[] kv = realVal.split(":");
String key = kv[0].trim();
String value = kv[1].trim();
MapEntry.Builder mapEntryBuilder = (MapEntry.Builder) currentBuilder.newBuilderForField(field);
final Descriptors.FieldDescriptor keyFieldDesc = mapEntryBuilder.getDescriptorForType().findFieldByName("key");
final Descriptors.FieldDescriptor valueFieldDesc = mapEntryBuilder.getDescriptorForType().findFieldByName("value");
mapEntryBuilder.setKey(buildValue(keyFieldDesc, key));
mapEntryBuilder.setField(valueFieldDesc, buildValue(valueFieldDesc, value));
currentBuilder.addRepeatedField(field, mapEntryBuilder.build());
}
public static Object buildValue(Descriptors.FieldDescriptor fieldDesc, String value){
final Descriptors.FieldDescriptor.JavaType javaType = fieldDesc.getJavaType();
switch (javaType) {
case ENUM:
return fieldDesc.getEnumType().findValueByNumber(Integer.valueOf(value));
case FLOAT:
return Float.valueOf(value);
case INT:
return Integer.valueOf(value);
case LONG:
return Long.valueOf(value);
case DOUBLE:
return Double.valueOf(value);
case BOOLEAN:
return Boolean.valueOf(value);
case BYTE_STRING:
return ByteString.copyFrom(DataConverters.hexString2ByteArray(value));
default:
return value;
}
}