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

Abh*_*kar 3 serialization protocol-buffers protobuf-java

给定一个原型文件:

\n
syntax = "proto3";\npackage hello;\n\nmessage TopGreeting {\n    NestedGreeting greeting = 1;\n}\n\nmessage NestedGreeting {\n    Greeting greeting = 1;\n}\n\nmessage Greeting {\n    string message = 1;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

和代码:

\n
public class Main {\n    public static void main(String[] args) {\n        System.out.printf("From top: %s%n", newGreeting("\xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?"));\n        System.out.printf("Directly: %s%n", "\xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?");\n        System.out.printf("ByteString: %s", newGreeting("\xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?").toByteString().toStringUtf8());\n    }\n\n    private static Hello.TopGreeting newGreeting(String message) {\n        Hello.Greeting greeting = Hello.Greeting.newBuilder()\n                .setMessage(message)\n                .build();\n        Hello.NestedGreeting nestedGreeting = Hello.NestedGreeting.newBuilder()\n                .setGreeting(greeting)\n                .build();\n        return Hello.TopGreeting.newBuilder()\n                .setGreeting(nestedGreeting)\n                .build();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
From top: greeting {\n  greeting {\n    message: "\\354\\230\\244\\353\\212\\230\\354\\235\\200 \\353\\254\\264\\354\\212\\250 \\354\\232\\224\\354\\235\\274\\354\\236\\205\\353\\213\\210\\352\\271\\214?"\n  }\n}\n\nDirectly: \xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?\n\nByteString: \n%\n#\n!\xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

Abh*_*kar 5

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

\n
System.out.println(TextFormat.printer().escapingNonAscii(false).printToString(greeting))\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
greeting {\n  greeting {\n    message: "\xec\x98\xa4\xeb\x8a\x98\xec\x9d\x80 \xeb\xac\xb4\xec\x8a\xa8 \xec\x9a\x94\xec\x9d\xbc\xec\x9e\x85\xeb\x8b\x88\xea\xb9\x8c?"\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n