由于表情符号,Go 在 JSON 输出中生成未转义的控制字符

Go is generating unescaped control characters in JSON output due to emoji

我在使用 Go 时遇到了一些问题,我不确定去哪里找。我正在从 MySQL 数据库中获取一个 UTF-8 字符串,并试图在对客户端的 JSON 响应中 return 它。

不同的客户端反应不同,但是iOS NSJSONSerialization return出现“未转义的控制字符”错误。这破坏了整个应用程序。不过,我可以使用 JSON.parse() 在 Chrome 中毫无问题地解码 JSON。

在服务器端,用 Go 之外的另一种语言编写的同一个生成器函数运行良好。有帮助吗?


编辑: 这是导致问题的 JSON:

{ "test":"☮️" }

...如果我省略这个表情符号,它就可以了。如果它在那里,它就不起作用。这个问题似乎与某些表情符号有两种不同的编码有关。一个似乎绊倒了围棋,但它们都是有效的。

为了展示编码的差异,一些表情符号会出现在数据库资源管理器中,而另一些则不会:

...这些出现在数据库资源管理器中的问题导致此问题具有 100% 的重现性。 然而,所有这些通常都毫无问题地出现在实际的客户端软件(而不是数据库浏览器)中。我不知道是否有办法重新配置数据库连接来避免这种情况(或东西),但它似乎适用于不同的实例,具体取决于解码的内容和宽容度。考虑到用户可以键入或 copy/paste 任一编码...这需要始终如一地工作。

如有任何帮助,我们将不胜感激。提前致谢。

Go 运行良好。

fmt.Println([]byte("☮️"))
//[226 152 174 239 184 143]
//Yup, 1 character - 6 bytes.

NSJSONSerialization 无法处理这个。 link 可能会有帮助 NSJSONSerialization and Emoji。这是关于 NSData * utf32Data = [uniText dataUsingEncoding:NSUTF32LittleEndianStringEncoding]; 的事情。废话

你能像我在 go 中那样给我们 "iOS style" 中“☮️”符号的字节表示吗?

UPD

我做了一些研究,看起来你的数据库编码有问题。是UTF16吗?

看看这个

// it look the same, but completely different "characters"
//first one is yours, and second one is U+262E
const nihongo = "☮️☮"
for index, runeValue := range nihongo {
        fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
}
bad := []byte("☮️")
good := []byte("☮")
fmt.Printf("%v %s \n", bad, bad)
fmt.Printf("%v %s \n", good, good)

输出:

U+262E '☮' starts at byte position 0
U+FE0F '️' starts at byte position 3
U+262E '☮' starts at byte position 6
[226 152 174 239 184 143] ☮️ 
[226 152 174] ☮ 

UDP2

它击中了我!我一直在用你的符号做 ctrl+c/ctrl+v 。但它不是一个单一的符号!它的 2 个符号和第二个是不可打印的。

unprintable := []byte{239, 184, 143}
fmt.Printf("valid? %v", utf8.Valid(unprintable))
fmt.Println("full rune?", utf8.FullRune(unprintable))
r, size := utf8.DecodeRune(unprintable)
fmt.Println(r, size, string(r))
fmt.Printf("valid rune? #v", utf8.ValidRune(r))

输出:

valid? true
full rune? true
65039 3 ️
valid rune? true

所以,你的数据库没问题,unprintable "character"没问题,但是 NSJSONSerialization 无法处理它。最好问 iOS 社区 =)