java - 如何将 Protocol Buffer 消息转换为 java 中的 HashMap?

标签 java java-8 protocol-buffers

我有一个形式的 protobuf 消息

enum PolicyValidationType {
    Number = 0;
}


message NumberPolicyValidation {
    optional int64 maxValue = 1;
    optional int64 minValue = 2;
}

message PolicyObject {
    required string key = 1;
    optional string value = 2;
    optional string name = 3;
    optional PolicyValidationType validationType = 4;
    optional NumberPolicyValidation numberPolicyValidation = 5;
}

例如

policyObject {
      key: "sessionIdleTimeoutInSecs"
      value: "1800"
      name: "Session Idle Timeout"
      validationType: Number
      numberPolicyValidation {
        maxValue: 3600
        minValue: 5
      }
}

谁能告诉我如何将其转换为如下所示的 Map:-

{validationType=Number, name=Session Idle Timeout, numberPolicyValidation={maxValue=3600.0, minValue=5.0}, value=1800, key=sessionIdleTimeoutInSecs}

我能想到的一种方法是将其转换为 json,然后将 json 转换为 map?

PolicyObject policyObject;
...
JsonFormat jsonFormat = new JsonFormat();
final String s = jsonFormat.printToString(policyObject);
Type objectMapType = new TypeToken<HashMap<String, Object>>() {}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(new TypeToken<HashMap<String,Object>>(){}.getType(), new PrimitiveDeserializer()).create();
Map<String, Object> mappedObject = gson.fromJson(s, objectMapType);

我认为一定有更好的方法。有人可以建议任何更好的方法吗?

最佳答案

我创建了小型专用类以将任何 Google Protocol Buffer 消息一般转换为 Java 映射。

public class ProtoUtil {

@NotNull
public 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;
}


@Nullable
/*package*/ Object convertVal(@NotNull Message proto, @NotNull Descriptors.FieldDescriptor fieldDescriptor, @Nullable 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;
}


@Nullable
/*package*/ Object convertAtomicVal(@NotNull Descriptors.FieldDescriptor fieldDescriptor, @Nullable 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;
}


}

希望对您有所帮助!分享和享受。

关于java - 如何将 Protocol Buffer 消息转换为 java 中的 HashMap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48821916/

相关文章:

java - Stream#reduce() 的 System.out.println() 意外在结果周围打印 "Optional[]"

java - 将对象提供给消费者并返回对象

java - 谷歌 Protocol Buffer pretty-print

java - 如何比较 Java 中的两个原型(prototype)缓冲区消息?

protocol-buffers - 如何在 proto buff 中对 byte[] 进行编码

java - HQL(hibernate) 时间戳范围匹配

java - 如何将 Future 转换为 Uni?

java - 使用具有可选值的构建器模式的更好方法?

java-8 - 对 lambda 的类型推断

java - 如何 sleep /等待 Java Swing 计时器