在实际使用protobuf传递消息的时候,如果本地pb文件与远端pb文件不一致,会导致本地将消息序列化为json字符串的时候,打印unknowFields的时候出现数字key,并且在该field可识别的字段都为空的时候,会出现以逗号开头,接着数字key的json片段,导致该json整体非法无法被其他json框架识别.
如下面的例子:
{“site”: {, “12”: [“c4-5”]}, “14”: [2]}
加粗的地方即为以(,)开始的非法json片段.
在protobuf-java-format-1.2 的版本中,
protected static void print(Message message, JsonGenerator generator) throws IOException {
for (Iterator<Map.Entry<FieldDescriptor, Object>> iter = message.getAllFields().entrySet().iterator(); iter
.hasNext();) {
Map.Entry<FieldDescriptor, Object> field = iter.next();
printField(field.getKey(), field.getValue(), generator);
if (iter.hasNext()) {
generator.print(",");
}
}
if (message.getUnknownFields().asMap().size() > 0)
generator.print(", ");
printUnknownFields(message.getUnknownFields(), generator);
}
在打印未知字段之前,会打印出问题所在的(,),基于结果可想而知上面那段代码没有执行进去,即该对象除了未知字段有值以外,其他已知字段都没有,导致打印出非法json片段.在这里完整copy jar包里的JsonFormat类的代码,修改下print方法为:
protected static void print(Message message, JsonGenerator generator) throws IOException {
boolean hasSetBefore = !message.getAllFields().entrySet().isEmpty();
for (Iterator<Map.Entry<FieldDescriptor, Object>> iter = message.getAllFields().entrySet().iterator(); iter
.hasNext();) {
Map.Entry<FieldDescriptor, Object> field = iter.next();
printField(field.getKey(), field.getValue(), generator);
if (iter.hasNext()) {
generator.print(",");
}
}
if (hasSetBefore && message.getUnknownFields().asMap().size() > 0)
generator.print(", ");
printUnknownFields(message.getUnknownFields(), generator);
}
在打印未知字段之前先判断现有已知字段是否都有值就行.