如何将Json转换为Protobuf?

0md85ypi  于 2022-12-27  发布在  其他
关注(0)|答案(5)|浏览(1182)

我是使用protobuf的新手,我想知道是否有一种简单的方法可以在Java中将json流/字符串转换为protobuf流/字符串?
例如,

protoString = convertToProto(jsonString)

我有一个json字符串,我想把它解析成一个protobuf消息,所以,我想先把这个json字符串转换成protobuf,然后在它上面调用Message.parseFrom()

ohfgkhjo

ohfgkhjo1#

在proto3中,你可以使用JsonFormat来完成这个任务,它直接解析JSON表示,所以不需要单独调用MyMessage.parseFrom(...)

JsonFormat.parser().merge(json_string, builder);
hujrc8aj

hujrc8aj2#

//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)
bvpmtnay

bvpmtnay3#

在线服务:https://json-to-proto.github.io/
这个工具可以将JSON立即转换成Protobuf。在左边粘贴一个JSON结构,右边就会生成一个等价的Protobuf,你可以将它粘贴到你的程序中。脚本必须做一些假设,所以请仔细检查输出!

ckx4rj1h

ckx4rj1h4#

由于有人询问如何获取异常“com.google.protobuf.InvalidProtocolBufferException:JsonObject”--我遇到了同样的问题。原来是由于Google protobuf时间戳。它们被序列化为一个包含两个字段“seconds”和“nanos”的对象,因为这不是生产代码,我只是通过使用Jackson解析JSON来绕过这个问题,递归地遍历JSON对象并将每个时间戳从对象更改为按照RFC 3339格式化的字符串,然后我把它序列化回来,并使用protobuf JSON解析器,如Adam所示。这解决了这个问题。这是我写的一些一次性代码(在我的例子中,所有时间戳字段都包含单词“timestamp”,这可能会更健壮,但我不在乎):

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;
}

不是最理想的解决方案,但它适用于我正在做的事情,我想我看到有人建议使用不同的时间戳类。

oymdgrw7

oymdgrw75#

您可以使用构建器和json String将json字符串转换为Proto
示例:

YourProto.Builder protoBuilder = YourProto.newBuilder();
JsonFormat.parser().merge(JsonString, protoBuilder);

如果要忽略未知json字段,则

YourProto.Builder protoBuilder = YourProto.newBuilder();
 JsonFormat.parser()..ignoringUnknownFields().merge(JsonString, protoBuilder);

另一种方法是使用ProtocolBuffer中的mergeFrom方法
示例:

YourProto.Builder protoBuilder = YourProto.newBuilder();
protoBuilder.mergeFrom(JsonString.getBytes());

一旦执行,您将从json String中获取protoBuilder中的所有数据

相关问题