【问题标题】:Protobuf map type JSON format uses string literal "key" and "value" not the actual valuesProtobuf 映射类型 JSON 格式使用字符串文字“键”和“值”而不是实际值
【发布时间】:2018-11-16 11:45:06
【问题描述】:

我正在尝试使用 com.googlecode.protobuf.format.JsonFormat 将 protobuf 对象转换为 JSON 格式,但 map 类型出乎意料。

我的留言是这样的

message Response {
   repeated Candidate candidates = 1;
   map<string, ErrorMessage> errors = 2;
}

message ErrorMessage {
   string message = 0;
   ErrorType type = 1;
}

enum ErrorType {
   ERROR = 0;
   WARNING = 1;
}

问题是我创建的 Response 对象的 JSON 格式

Response response = ...
Return new ResponseEntity<>(new JsonFormat().printToString(response), HttpStatus.OK);

我希望错误被格式化为由字符串值(映射键的)键控的映射

...
"errors": {
  "someID" : {
      "message": "blah blah",
      "type": "ERROR"
  }
}

但是 实际 输出是(我只评估了 intellij 中的 new JsonFormat().printToString(response) 部分)

...
"errors": {
  "key": "someID",
  "value": {
      "message": "blah blah",
      "type": "ERROR"
  }
}

我希望我错过了一些小配置来制作 protobuf(或 Jackson?)以了解实际的键值?不使用“键”和“值”。

顺便说一句,在 map 类型中包含文字“键”和“值”字段有什么意义?您不能使用它进行成分查找,您可能只使用自定义类型/对象。

【问题讨论】:

    标签: java json serialization protocol-buffers protobuf-java


    【解决方案1】:

    这段代码非常适合我:

    test.proto

    syntax = "proto2";
    package by.dev.madhead;
    option java_outer_classname = "SO";
    
    message Candidate {
    
    }
    
    enum ErrorType {
        ERROR = 0;
        WARNING = 1;
    }
    
    message ErrorMessage {
        required string message = 1;
        required ErrorType type = 2;
    }
    
    message Response {
        repeated Candidate candidates = 1;
        map<string, ErrorMessage> errors = 2;
    }
    

    App.java

    public class App {
        public static void main(String[] args) throws InvalidProtocolBufferException {
            SO.Response response = SO.Response.newBuilder()
                .addCandidates(SO.Candidate.newBuilder().build())
                .addCandidates(SO.Candidate.newBuilder().build())
                .addCandidates(SO.Candidate.newBuilder().build())
                .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
                .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
                .build();
    
            System.out.println(JsonFormat.printer().print(response));
        }
    }
    

    输出是:

    {
        "candidates": [{
        }, {
        }, {
        }],
        "errors": {
            "error1": {
                "message": "error1",
                "type": "ERROR"
            },
            "error2": {
                "message": "error2",
                "type": "WARNING"
            }
        }
    }
    

    如您所见,没有keys 和value。确保您打印的不是消息本身,而是JsonFormat.printer().print() 的结果。基本上,您看到的keyvalues 来自Protobuf Message 的内部toString() 实现。

    JsonFormat 的完整类名是 com.google.protobuf.util.JsonFormat,而不是 com.googlecode.protobuf.format.JsonFormat

    【讨论】:

    • 感谢您的帮助!事实上,我使用了com.googlecode.protobuf.format.JsonFormat 而不是com.google.protobuf.util.JsonFormat,这就是问题所在。 googlecode one 似乎是一个过时的格式化工具?
    • 我想,是的,它已经过时了。所有 Google 搜索结果均指向 com.google.protobuf.util.JsonFormat
    猜你喜欢
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 2014-04-20
    • 2021-01-14
    • 1970-01-01
    相关资源
    最近更新 更多