前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JSON 序列化中的转义和 Unicode 编码

JSON 序列化中的转义和 Unicode 编码

原创
作者头像
amc
修改2020-05-09 13:12:26
9.2K0
修改2020-05-09 13:12:26
举报
文章被收录于专栏:后台全栈之路后台全栈之路

本文比较完整地整理一下 JSON 编码中的转义,以及 JSON 对 Unicode 编码的处理。

其实这是我上一篇文章的姊妹篇。在研究 Unicode 颜文字的时候,由于我们的数据传输是通过 JSON 串来完成的,在对颜文字进行转码传输的过程中,也发现了一个问题。解决问题之后,便有了本总结文。

JSON 中的普通转义字符

个人认为,JSON 是目前针对程序员而言可读性(readability)最佳的数据传输格式之一,并且 JSON 完整地考虑到了数据传输中的转义,避免出现各种注入风险。当对 JSON 进行序列化操作时(Go 中称为 marshal),根据 JSON 标准的说明,需要对字符串中的以下字符进行转义:

符号

名称

转义后的字符串

"

双引号

\"

/

斜杠

\/

\

反斜杠

\\

\b

退格符

\b

\f

垂直制表符

\f

Tab

水平制表符

\t

\r

回车

\r

\n

换行符

\n

<

左尖括号

\u003C

>

右尖括号

\u003E

&

And 符号

\u0026

另外针对 Go 语言,个人建议再转义一个百分号 %\u0025,原因是在 Go 的各种字符串格式化操作中,百分号是一个关键字符,这样可以避免在打日志或者其他设计格式化的操作时出现错误。

JSON 中针对 Unicode 字符的处理

这里所说的 Unicode 字符,准确而言指的是在 ASCII 范围之外的字符,也就是值大于 0x7F 的 Unicode 字符。

其实大部分情况下,UTF-8 已经成为现代编程语言约定俗成的标准了,因此在 JSON 序列化时,只要简单地对 Unicode 字符的值转为二进制然后按照网络字节序打包就可以了。

但是在某些情况下,当对端采用的不是 UTF-8,或者是对端采用的不是网络字节序时(比如对方是技术底下/落后、但却话语权强大的客户/合作商/集成商),这个时候,大家统一采用 ASCII 编码,就能够避免这些问题了。

那么 JSON 是怎么使用 ASCII 编码来传输 Unicode 的呢?从前文的转义其实就可以一窥端倪了——JSON 采用的是 \uXXXX 的形式来表示一个 Unicode 字符的。每个 Unicode 字符表示法中,XXXX 必须是4个十六进制数,即便高位为0也需要补全。通过这种方式,编码和传输 Unicode 字符。在 ASCII 为主的数据传输中,这种编码方式比较稳妥,并且不会额外增加过多的数据量。当然对于 Unicode 字符比较多的情况下(比如大量的中文),这就需要程序员考虑一下额外带来的网络花销了。

大于 0xFFFF 的 Unicode 字符的编码

读者可能会注意到了,\uXXXX 格式最大只能支持到 0xFFFF,但 Unicode 早就已经超过了这个范围。大于 65535 的字符要怎么表示呢?首先,绝对不是简单地采用 \uXXXXX,这会导致编码错误。

针对大于 65535 的字符,JSON 采用的是 UTF-16 编码。UTF-16 采用了 Unicode 的一个特性:不超过20位。

比如我们用 u 代表这样的一个字符,UTF-16 的处理方法如下:

  • 首先,u = u - 0x10000
  • hi 等于做了减法之后的 u 的高10位:hi = (u & 0xFFC00) >> 10
  • lo 等于做了减法之后的 u 的低10位:lo = u & 0x003FF
  • 高位加上 0xD800 后进行 \u 编码
  • 低位加上 0xDC00 后进行 \u 编码

举例说明:代表地球的颜文字符号 “🌍”,其编码值为 0x1F30D,按照 UTF-16 编码过程为:

  • u = 0x1F30D - 0x10000 = 0xF30D,二进制:1111 0011 0000 1101
  • 高10位等于 0000111100,低10位等于 1100001101
  • 高位值 0x03C 做加法之后等于 0xD83C
  • 低位值 0x30D 做加法之后等于 0xDF0D
  • 最终编码为 \uD83C\uDF0D

比如以下的 JSON:

代码语言:txt
复制
{
    "string":"我是地球🌍"
}

按照 ASCII 序列化之后,结果为:

{"string":"\u6211\u662F\u5730\u7403\uD83C\uDF0D"}

参考资料


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题:JSON 序列化中的转义和 Unicode 编码

发布日期:2020-05-09

原文链接:https://cloud.tencent.com/developer/article/1625557

Copyright
Copyright

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JSON 中的普通转义字符
  • JSON 中针对 Unicode 字符的处理
  • 大于 0xFFFF 的 Unicode 字符的编码
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档