我是使用protobuf的新手,并且想知道是否有一种简单的方法可以将Java中的json流/字符串转换为protobuf流/字符串?
例如,
protoString = convertToProto(jsonString)
我有一个json字符串,我想解析为protobuf消息。所以,我想首先将json字符串转换为protobuf,然后在其上调用Message.parseFrom()
。
提前感谢您的帮助!
答案 0 :(得分:18)
使用proto3,您可以使用JsonFormat执行此操作。它直接从JSON表示解析,因此不需要单独调用MyMessage.parseFrom(...)
。这样的事情应该有效:
JsonFormat.parser().merge(json_string, builder);
答案 1 :(得分:1)
//You can use this for converting your input json to a Struct / any other Protobuf Class
import com.google.protobuf.Struct.Builder;
import com.google.protobuf.Struct;
import com.google.protobuf.util.JsonFormat;
import org.json.JSONObject;
JSONObject parameters = new JSONObject();
Builder structBuilder = Struct.newBuilder();
JsonFormat.parser().merge(parameters.toString(), structBuilder);
// Now use the structBuilder to pass below (I used it for Dialog Flow V2 Context Management)
答案 2 :(得分:0)
在线服务: https://json-to-proto.github.io/
<块引用>此工具可立即将 JSON 转换为 Protobuf。在左侧粘贴一个 JSON 结构,右侧将生成等效的 Protobuf,您可以将其粘贴到您的程序中。脚本必须做出一些假设,因此请仔细检查输出!
答案 3 :(得分:0)
由于有人询问在遵循 Adam 的建议时是否会收到异常“com.google.protobuf.InvalidProtocolBufferException: JsonObject”——我遇到了同样的问题。原来这是由于 google protobuf 时间戳。它们被序列化为包含两个字段“seconds”和“nanos”的对象,因为这不是生产代码,我只是通过使用 jackson 解析 JSON、递归遍历 JSON 对象并更改每个时间戳来解决这个问题对象转换为按照 RFC 3339 格式化的字符串,然后我将其序列化并使用 Adam 所示的 protobuf JSON 解析器。这解决了这个问题。这是我写的一些一次性代码(在我的例子中所有时间戳字段都包含“时间戳”这个词,这可能更健壮,但我不在乎):
public Map<String, Object> fixJsonTimestamps(Map<String, Object> inMap) {
Map<String, Object> outMap = new HashMap<>();
for(String key : inMap.keySet()) {
Object val = inMap.get(key);
if(val instanceof Map) {
Map<String, Object> valMap = (Map<String, Object>)val;
if(key.toLowerCase().contains("timestamp") &&
valMap.containsKey("seconds") && valMap.containsKey("nanos")) {
if(valMap.get("seconds") != null) {
ZonedDateTime d = ZonedDateTime.ofInstant(Instant.ofEpochSecond((int)valMap.get("seconds")).plusNanos((int)valMap.get("nanos")),
ZoneId.of("UTC"));
val = d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
}
} else {
val = fixJsonTimestamps(valMap);
}
} else if(val instanceof List && ((List) val).size() > 0 &&
((List) val).get(0) instanceof Map) {
List<Map<String, Object>> outputList = new ArrayList<>();
for(Map item : (List<Map>)val) {
outputList.add(fixJsonTimestamps(item));
}
val = outputList;
}
outMap.put(key, val);
}
return outMap;
}
不是最理想的解决方案,但它适用于我正在做的事情,我想我看到有人推荐使用不同的时间戳类。