0

我正在尝试将 json 转换为原始消息对象,但是如果 json 中有一些字符,例如 $ 或 . 或 _ 我得到一个 InvalidProtocolBufferException。我的原型:

syntax = "proto3";

package messages;
option java_multiple_files = true;

message Main {
    A a = 1;
}

message A {
    repeated B b = 1;
}

message B {
    repeated C c = 1;
}

message C {
    map<string, bytes> d = 1;
}

Java代码:

 String json = "{\n" +
        "  \"a\" : {\n" +
        "    \"b\" : [ {\n" +
        "      \"c\" : [ {\n" +
        "        \"d\" : {\n" +
        "          \"money\" : [ \"100$\" ]\n" +
        "        }\n" +
        "      } ]\n" +
        "    } ]\n" +
        "  }\n" +
        "}";
    Main.Builder builder = Main.newBuilder();
    JsonFormat.parser().merge(json, builder);
    System.out.println(builder.build());

输出:

  com.google.protobuf.InvalidProtocolBufferException: com.google.common.io.BaseEncoding$DecodingException: Unrecognized character: $

        at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1065)
        at com.google.protobuf.util.JsonFormat$Parser.merge(JsonFormat.java:273)
4

1 回答 1

0

在我看来,您的问题与类型 C 的声明有关,在它的内部,在 proto 定义中,您map<string,bytes> d = 1;在 Java 方面将是:Map<String, ByteString>并且在您的 Json 中,您有一些“看起来像”String-String 映射的东西。

让我们做一个快速实验并尝试将您的 Main 类型转换为 json:

Main main = Main.newBuilder().setA(
        A.newBuilder().addB(
                B.newBuilder().addC(
                        C.newBuilder().putD("money", 
                                ByteString.copyFrom("100$".getBytes()))
                )
        )
).build();

System.out.println(JsonFormat.printer().print(main));

输出将是

{
  "a": {
    "b": [{
      "c": [{
        "d": {
          "money": "MTAwJA=="
        }
      }]
    }]
  }
}

如您所见,我们没有100$编码版本MTAwJA==,如果您尝试使用 protobuf 将此 json 转换为对象,则不会出错。

所以在我看来 - 要么在转换为 json 期间在你的 d 映射中编码值(或使用 protobuf 转换为 json),或者更改 protobuf 声明

于 2017-02-17T20:29:56.933 回答