如何以人类可读的方式记录嵌套对象中的Protobuf字符串



给定一个原型文件:

syntax = "proto3";
package hello;
message TopGreeting {
NestedGreeting greeting = 1;
}
message NestedGreeting {
Greeting greeting = 1;
}
message Greeting {
string message = 1;
}

代码:

public class Main {
public static void main(String[] args) {
System.out.printf("From top: %s%n", newGreeting("오늘은 무슨 요일입니까?"));
System.out.printf("Directly: %s%n", "오늘은 무슨 요일입니까?");
System.out.printf("ByteString: %s", newGreeting("오늘은 무슨 요일입니까?").toByteString().toStringUtf8());
}
private static Hello.TopGreeting newGreeting(String message) {
Hello.Greeting greeting = Hello.Greeting.newBuilder()
.setMessage(message)
.build();
Hello.NestedGreeting nestedGreeting = Hello.NestedGreeting.newBuilder()
.setGreeting(greeting)
.build();
return Hello.TopGreeting.newBuilder()
.setGreeting(nestedGreeting)
.build();
}
}

输出

From top: greeting {
greeting {
message: "354230244353212230354235200 353254264354212250 354232224354235274354236205353213210352271214?"
}
}
Directly: 오늘은 무슨 요일입니까?
ByteString: 
%
#
!오늘은 무슨 요일입니까?

如何以可读的方式打印消息?正如您所看到的,转换为ByteString可以打印UTF-8字符,但也可以打印其他一些垃圾%#

在回答我自己的问题时,我通过挖掘Protobuf源代码解决了这个问题。

System.out.println(TextFormat.printer().escapingNonAscii(false).printToString(greeting))

输出:

greeting {
greeting {
message: "오늘은 무슨 요일입니까?"
}
}

toString使用相同的机制,但使用escapingNonAscii(true)(省略时为默认值(。

另请参阅此答案,了解如何将Octal序列转换为UTF-8字符,以防您无法访问源代码,只能访问日志。

protobuf二进制格式不是可读的,你不应该试图让它成为可读的。如果你需要的话,有一个JSON变体,但坦率地说,最好记录解释的数据,而不是有效载荷。