Python 3中的json.dumps,会将中文转换为unicode编码后保存

先把这次踩坑的结论放在最前面

1. Python 3已经将unicode作为默认编码

2. Python 3中的json在做dumps操作时,会将中文转换成unicode编码,并以16进制方式存储,再做逆向操作时,会将unicode编码转换回中文

这就解释了,为什么json.dumps操作后,得到的字符串是\uXXXX。

谢谢@benpaodexiaowoniu。

在python3中,ensure_ascii=False就解决了问题

------------------分割线以下部分纯属扯淡,没时间的现在可以关闭页面了-------------------------

 

如果不知道上面两点,加之python之前对编码处理的不好名声,就会陷入一个问题深坑中。

读到这里,如果你赶时间,就可以不用往下看了。

爆出问题的代码如下:

@app.route("/<desc>/<amount>")

def addSimpleRecord(desc, amount):

    .....

        file.write(json.dumps(buildJson(desc, amount)));

    ....

整个程序运行正常,但当我打开文件看到保存的中文数据变成了\uXXXX时,头都大了。

经过了各种尝试,我发现网上对python3中的编码问题进行了如下归纳

  1. \uXXXX是unicode 16进制编码的表现形式
  2. 在文件的第一行加上# -*- coding: utf-8 -*-
  3. 对字符串对象进行str.decode('...').encode('...')
  4. 对字符串对象进行操作:str.encode('utf-8').decode('unicode_escape')

关于第一条,print("你" == "\u4f60")得到的结果是True

关于第二条,那是python2的故事,在python3中默认的文件编码就是utf-8。因此,在保存python 3的脚本时,请务必保存为utf-8。

关于第三条,那也是python2的故事,在python3中,字符串默认采用unicode编码。

关于第四条,最初我是参考 python3 把\u开头的unicode转中文,把str形态的unicode转中文 ,发现不能重现,后来当我用\\uXXXX时,就重现了这篇文章中描述的问题,因为\在python字符串中起转义作用(我居然给忘记了)。

 

为什么json.dumps处理过后的中文就变成了\uXXXX呢?原因在这里py_encode_basestring_ascii

 

ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
HAS_UTF8 = re.compile(b'[\x80-\xff]')
ESCAPE_DCT = {
    '\\': '\\\\',
    '"': '\\"',
    '\b': '\\b',
    '\f': '\\f',
    '\n': '\\n',
    '\r': '\\r',
    '\t': '\\t',
}

def py_encode_basestring_ascii(s):
    """Return an ASCII-only JSON representation of a Python string
    """
    def replace(match):
        s = match.group(0)
        try:
            return ESCAPE_DCT[s]
        except KeyError:
            n = ord(s)
            if n < 0x10000:
                return '\\u{0:04x}'.format(n)
                #return '\\u%04x' % (n,)
            else:
                # surrogate pair
                n -= 0x10000
                s1 = 0xd800 | ((n >> 10) & 0x3ff)
                s2 = 0xdc00 | (n & 0x3ff)
                return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
    return '"' + ESCAPE_ASCII.sub(replace, s) + '"'

 

关键的地方就在:

return '\\u{0:04x}'.format(n)

其中{0:04x}表示取第一个参数,并取长度为4的16进制小写数字。

json.dumps的参数中有一个参数ensure_ascii,其默认值为True。我想这么做的目的可能是为了跨平台的通用性。

 

到此为止,python 3的编码问题总算是告一段落,如有问题,欢迎交流。

  • 27
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明天好,会的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值