json_dumps(dict)时,如果dict包含有汉字,一定加上ensure_ascii=False。否则按参数默认值True,意思是保证dumps之后的结果里所有的字符都能够被ascii表示,汉字在ascii的字符集里面,因此经过dumps以后的str里,汉字会变成对应的unicode。
虽然在Python3 里面汉字在内存里就是unicode表示,这里str里面的unicode经过loads也能还原成汉字,看起来似乎没什么问题。
但这样的操作只适合python,你能这么做事因为python认识unicode,python在执行json.loads的时候知道unicode是用来表示汉字而不是真的几个char拼接在一起,所以会对“\u”开头的这种字符串做转义理解。
不过以上转义理解是python中json.dumps和loads自己所遵守的规则,并不是通用的规则。
如果你脱离了python,比如把这串字符串以一定的方式送出去(写入文件或者通过网络发送),给另外的应用程序(比如记事本)处理,这个应用看到“\u45ef”就会老老实实的认为这是1个包含了6个char的字符串,绝不会跟1个汉字扯上联系。
另外,经过json.dumps(dict),拿到的str看起来和dic长得很像,但实际含义很不一样。
这是比较容易被迷惑的地方。
dict是有层次有标准结构的,这就是你可以对dict执行dict.get(one_key)从里面提取不同层次的内容;但是dumps成str以后,虽然表示层次的{}和[]符号都在,但此时的str就是1个从头到尾的线性序列,层次、键值的关系已经消失了,这意味着你也没法按字段去取。
所以,dumps后str里面的unicode,就是6个字符,只有python中json.loads()会按转义理解为汉字,但是这个str给到其他应用,就是6个字符,如此而已。
如何对字典里面的汉字进行查找替换?
dic.replace?(×)
str(dic) -> str.replace() -> json.loads(str)? (×)
dump成str -> str.replace() ->load转回dic?(√)
>>> a = {"hello" : "好"}
>>> hasattr(a,'replace')
False # 没有API,行不通
>>> b = str(a).replace("好","你好")
>>> b
"{'hello': '你好'}"
>>> json.loads(b) #也行不通,json只认双引号
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\Grace\AppData\Local\Programs\Python\Python36\lib\json\__init__.py", line 354, in loads
return _default_decoder.decode(s)
File "C:\Users\Grace\AppData\Local\Programs\Python\Python36\lib\json\decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Users\Grace\AppData\Local\Programs\Python\Python36\lib\json\decoder.py", line 355, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
>>> a
{'hello': '好'}
>>> c = json.dumps(a)
>>> c
'{"hello": "\\u597d"}'
>>> c.replace("好","你好")
'{"hello": "\\u597d"}'
>>> c[11]
'\\'
>>> len(c) #c 里面包含19个char,根本没有中文
19
>>> d = json.dumps(a, ensure_ascii=False) #带上这个参数
>>> d
'{"hello": "好"}'
>>> d.replace("好", "你好")
'{"hello": "你好"}'
>>> json.loads(d.replace("好", "你好"))
{'hello': '你好'}
json.loads 不仅可以dict转str,也可以把其他对象比如1个class转str。这种转换是表示层面的。
str不是bytes,为了写入文件或者网络传输,str还得转换成bytes,这个转换是在通信层面。