我正在使用 Python 2 来解析 ASCII编码文本文件中的JSON。
使用json
或simplejson
加载这些文件时,我的所有字符串值都会转换为Unicode对象而不是字符串对象。问题是,我必须使用一些只接受字符串对象的库的数据。我无法更改库也无法更新它们。
是否可以获取字符串对象而不是Unicode对象?
>>> import json
>>> original_list = ['a', 'b']
>>> json_list = json.dumps(original_list)
>>> json_list
'["a", "b"]'
>>> new_list = json.loads(json_list)
>>> new_list
[u'a', u'b'] # I want these to be of type `str`, not `unicode`
很久以前问了这个问题,当我遇到 Python 2 时。今天一个简单而干净的解决方案是使用最新版本的Python - 即 Python 3 并转发。
答案 0 :(得分:174)
虽然这里有一些很好的答案,但我最终使用PyYAML来解析我的JSON文件,因为它将键和值设为str
类型字符串而不是unicode
类型。因为JSON是YAML的一个子集,所以它可以很好地工作:
>>> import json
>>> import yaml
>>> list_org = ['a', 'b']
>>> list_dump = json.dumps(list_org)
>>> list_dump
'["a", "b"]'
>>> json.loads(list_dump)
[u'a', u'b']
>>> yaml.safe_load(list_dump)
['a', 'b']
有些事情需要注意:
我得到字符串对象,因为我的所有条目都是 ASCII编码。如果我使用unicode编码的条目,我会把它们作为 unicode对象取回 - 没有转换!
你应该(可能总是)使用PyYAML的safe_load
函数;如果您使用它来加载JSON文件,则无论如何都不需要load
函数的“额外功能”。
如果您希望YAML解析器对规范的1.2版本(以及correctly parses very low numbers)有更多支持,请尝试Ruamel YAML:pip install ruamel.yaml
和import ruamel.yaml as yaml
我在测试中所需要的一切。
如上所述,没有转换!如果你不能确定只处理ASCII值(并且你大多数时候都不能确定),那么最好使用转换函数:
我现在使用过Mark Amery次的那个,效果很好而且非常容易使用。您也可以使用与object_hook
类似的功能,因为它可能会提升大文件的性能。请参阅稍微复杂一点的answer from Mirec Miskuf。
答案 1 :(得分:139)
没有内置选项使json模块函数返回字节字符串而不是unicode字符串。但是,这个简短而简单的递归函数会将任何已解码的JSON对象从使用unicode字符串转换为UTF-8编码的字节字符串:
def byteify(input):
if isinstance(input, dict):
return {byteify(key): byteify(value)
for key, value in input.iteritems()}
elif isinstance(input, list):
return [byteify(element) for element in input]
elif isinstance(input, unicode):
return input.encode('utf-8')
else:
return input
只需通过json.load
或json.loads
来电获得的输出即可。
几点说明:
return {byteify(key): byteify(value) for key, value in input.iteritems()}
替换为return dict([(byteify(key), byteify(value)) for key, value in input.iteritems()])
,因为在Python 2.7之前不支持字典理解。object_hook
或object_pairs_hook
参数来避免这些特性。到目前为止,Mirec Miskuf's answer是唯一一个能够正确解决问题的人,尽管如此,它比我的方法复杂得多。答案 2 :(得分:91)
object_hook
import json
def json_load_byteified(file_handle):
return _byteify(
json.load(file_handle, object_hook=_byteify),
ignore_dicts=True
)
def json_loads_byteified(json_text):
return _byteify(
json.loads(json_text, object_hook=_byteify),
ignore_dicts=True
)
def _byteify(data, ignore_dicts = False):
# if this is a unicode string, return its string representation
if isinstance(data, unicode):
return data.encode('utf-8')
# if this is a list of values, return list of byteified values
if isinstance(data, list):
return [ _byteify(item, ignore_dicts=True) for item in data ]
# if this is a dictionary, return dictionary of byteified keys and values
# but only if we haven't already byteified it
if isinstance(data, dict) and not ignore_dicts:
return {
_byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True)
for key, value in data.iteritems()
}
# if it's anything else, return it in its original form
return data
使用示例:
>>> json_loads_byteified('{"Hello": "World"}')
{'Hello': 'World'}
>>> json_loads_byteified('"I am a top-level string"')
'I am a top-level string'
>>> json_loads_byteified('7')
7
>>> json_loads_byteified('["I am inside a list"]')
['I am inside a list']
>>> json_loads_byteified('[[[[[[[["I am inside a big nest of lists"]]]]]]]]')
[[[[[[[['I am inside a big nest of lists']]]]]]]]
>>> json_loads_byteified('{"foo": "bar", "things": [7, {"qux": "baz", "moo": {"cow": ["milk"]}}]}')
{'things': [7, {'qux': 'baz', 'moo': {'cow': ['milk']}}], 'foo': 'bar'}
>>> json_load_byteified(open('somefile.json'))
{'more json': 'from a file'}
Mark Amery's function比这些更短更清晰,那么它们有什么意义呢?你为什么要使用它们?
纯粹为表现。 Mark的回答首先使用unicode字符串完全解码JSON文本,然后通过整个解码值进行递归,将所有字符串转换为字节字符串。这有几个不良影响:
此答案通过使用object_hook
和json.load
的{{1}}参数来缓解这两个性能问题。来自the docs:
json.loads
是一个可选函数,将使用任何对象文字解码的结果调用(object_hook
)。将使用object_hook的返回值而不是dict
。此功能可用于实现自定义解码器
由于字典嵌套在其他字典深处的许多级别被传递给dict
,因为它们已被解码,我们可以在那时对其中的任何字符串或列表进行字节化,并避免需要后来深度递归。
Mark的答案不适合用作object_hook
,因为它会递归到嵌套的词典中。我们使用object_hook
参数ignore_dicts
来阻止此答案中的递归,_byteify
传递给它{em>除时object_hook
传递新dict
ignore_dicts
1}}字节化。 _byteify
标记告诉dict
忽略json_load_byteified
,因为它们已被字节化。
最后,我们对json_loads_byteified
和_byteify
的实施调用ignore_dicts=True
(json.load
)对json.loads
或dict
返回的结果处理正在解码的JSON文本在顶层没有data.table
的情况。
答案 3 :(得分:73)
您可以使用json.loads
的object_hook
参数传入转换器。事后你不必进行转换。 json
模块将始终仅传递object_hook
dicts,并且它将递归传递嵌套的dicts,因此您不必自己递归到嵌套的dicts。我不认为我会将unicode字符串转换为Wells节目等数字。如果它是一个unicode字符串,它在JSON文件中被引用为一个字符串,所以它应该是一个字符串(或者文件很糟糕)。
另外,我会尽量避免在str(val)
对象上执行unicode
之类的操作。您应该将value.encode(encoding)
与有效编码一起使用,具体取决于外部lib期望的内容。
所以,例如:
def _decode_list(data):
rv = []
for item in data:
if isinstance(item, unicode):
item = item.encode('utf-8')
elif isinstance(item, list):
item = _decode_list(item)
elif isinstance(item, dict):
item = _decode_dict(item)
rv.append(item)
return rv
def _decode_dict(data):
rv = {}
for key, value in data.iteritems():
if isinstance(key, unicode):
key = key.encode('utf-8')
if isinstance(value, unicode):
value = value.encode('utf-8')
elif isinstance(value, list):
value = _decode_list(value)
elif isinstance(value, dict):
value = _decode_dict(value)
rv[key] = value
return rv
obj = json.loads(s, object_hook=_decode_dict)
答案 4 :(得分:37)
那是因为json在字符串对象和unicode对象之间没有区别。它们都是javascript中的所有字符串。
我认为 JSON是正确的返回unicode对象。事实上,我不会接受任何更少,因为javascript字符串实际上是unicode
个对象(即JSON(javascript)字符串可以存储任何类型的的unicode因此,在从JSON转换字符串时创建unicode
对象是有意义的。简单的字符串是不适合的,因为库必须猜测你想要的编码。
最好在任何地方使用unicode
字符串对象。因此,最好的选择是更新库,以便它们可以处理unicode对象。
但如果您真的想要字节串,只需将结果编码为您选择的编码:
>>> nl = json.loads(js)
>>> nl
[u'a', u'b']
>>> nl = [s.encode('utf-8') for s in nl]
>>> nl
['a', 'b']
答案 5 :(得分:14)
有一种简单的解决方法。
TL; DR - 使用ast.literal_eval()
代替json.loads()
。 ast
和json
都在标准库中。
虽然不是一个完美的'回答,如果您的计划完全忽略Unicode,它会得到一个很好的结果。在Python 2.7中
import json, ast
d = { 'field' : 'value' }
print "JSON Fail: ", json.loads(json.dumps(d))
print "AST Win:", ast.literal_eval(json.dumps(d))
给出:
JSON Fail: {u'field': u'value'}
AST Win: {'field': 'value'}
当某些对象真的是Unicode字符串时,这会变得更加毛茸茸。完整的答案会很快变成毛茸茸的。
答案 6 :(得分:11)
Mike Brennan's answer已接近,但没有理由重新遍历整个结构。如果您使用object_hook_pairs
(Python 2.7+)参数:
object_pairs_hook
是一个可选函数,将使用对有序列表对解码的任何对象文字的结果进行调用。将使用object_pairs_hook
的返回值代替dict
。此功能可用于实现依赖于键和值对解码顺序的自定义解码器(例如,collections.OrderedDict
将记住插入顺序)。如果还定义了object_hook
,则object_pairs_hook
优先。
有了它,你就会得到每个JSON对象,所以你可以在不需要递归的情况下进行解码:
def deunicodify_hook(pairs):
new_pairs = []
for key, value in pairs:
if isinstance(value, unicode):
value = value.encode('utf-8')
if isinstance(key, unicode):
key = key.encode('utf-8')
new_pairs.append((key, value))
return dict(new_pairs)
In [52]: open('test.json').read()
Out[52]: '{"1": "hello", "abc": [1, 2, 3], "def": {"hi": "mom"}, "boo": [1, "hi", "moo", {"5": "some"}]}'
In [53]: json.load(open('test.json'))
Out[53]:
{u'1': u'hello',
u'abc': [1, 2, 3],
u'boo': [1, u'hi', u'moo', {u'5': u'some'}],
u'def': {u'hi': u'mom'}}
In [54]: json.load(open('test.json'), object_pairs_hook=deunicodify_hook)
Out[54]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
请注意,我永远不必递归地调用钩子,因为当你使用object_pairs_hook
时,每个对象都会被传递给钩子。您必须关心列表,但正如您所看到的,列表中的对象将被正确转换,您无需递归即可实现。
编辑:一位同事指出Python2.6没有object_hook_pairs
。您仍然可以通过进行非常小的更改来使用Python2.6。在上面的钩子中,改变:
for key, value in pairs:
到
for key, value in pairs.iteritems():
然后使用object_hook
代替object_pairs_hook
:
In [66]: json.load(open('test.json'), object_hook=deunicodify_hook)
Out[66]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
使用object_pairs_hook
会导致为JSON对象中的每个对象实例化一个较少的字典,如果您正在解析一个巨大的文档,那么它可能值得一试。
答案 7 :(得分:9)
我担心在simplejson库中无法自动实现这一点。
simplejson中的扫描仪和解码器旨在生成unicode文本。为此,库使用名为c_scanstring
的函数(如果可用,速度为快),如果C版本不可用,则使用py_scanstring
。几乎所有simplejson用于解码可能包含文本的结构的例程都会多次调用scanstring
函数。您必须在simplejson.decoder或子类scanstring
中对JSONDecoder
值进行monkeypatch,并提供几乎所有可能包含文本的实现。
然而,simplejson输出unicode的原因是json spec特别提到“字符串是零个或多个Unicode字符的集合”......对unicode的支持被假定为格式本身的一部分。 Simplejson的scanstring
实现甚至扫描和解释unicode转义(甚至错误检查格式错误的多字节字符集表示),因此它可以可靠地将值返回给你的唯一方法是unicode。
如果您有一个需要str
的老化库,我建议您在解析后仔细搜索嵌套数据结构(我承认您明确表示要避免...抱歉),或者或许将您的库包装在某种外观中,您可以在更精细的层面上按下输入参数。如果您的数据结构确实是嵌套的,那么第二种方法可能比第一种方法更易于管理。
答案 8 :(得分:4)
正如Mark(Amery)正确指出:在json转储上使用 PyYaml 的反序列化器仅在您只有ASCII时才有效。至少开箱即用。
关于PyYaml方法的两个快速评论:
NEVER对来自该字段的数据使用yaml.load。它是yaml的一个特性(!),用于执行隐藏在结构中的任意代码。
可以通过以下方式使其适用于非ASCII:
def to_utf8(loader, node):
return loader.construct_scalar(node).encode('utf-8')
yaml.add_constructor(u'tag:yaml.org,2002:str', to_utf8)
但表现明智,与马克·阿梅里的答案无法比较:
将两个深层嵌套的样本序列扔到两个方法上,我得到了这个(使用dt [j] = json.loads的时间增量(json.dumps(m))):
dt[yaml.safe_load(json.dumps(m))] =~ 100 * dt[j]
dt[byteify recursion(Mark Amery)] =~ 5 * dt[j]
所以反序列化包括完全遍历树和编码,完全在json基于C的实现的数量级内。我发现它非常快,并且它比深嵌套结构中的yaml负载更强大。并且更容易出现安全性错误,请查看yaml.load。
=>虽然我很欣赏指向基于C的转换器的指针,但 byteify函数应该是默认答案。
如果您的json结构来自包含用户输入的字段,则尤其如此。因为那时你可能需要在你的结构上走 - 独立于你想要的内部数据结构('unicode sandwich'或仅字节字符串)。
为什么?
Unicode 规范化。对于不知情的人:拿一个止痛药并阅读this。
因此,使用byteify递归可以一举两得:
在我的测试中,结果发现用unicodedata.normalize('NFC',输入).encode('utf-8')替换input.encode('utf-8')比使用w / o更快NFC - 但这很大程度上取决于我猜测的样本数据。
答案 9 :(得分:3)
问题是simplejson
和json
是两个不同的模块,至少以它们处理unicode的方式。你在py 2.6+中有json
,这给你unicode值,而simplejson
返回字符串对象。只需在您的环境中尝试easy_install-ing simplejson,看看是否有效。它确实适合我。
答案 10 :(得分:2)
只需使用pickle代替json进行转储和加载,如下所示:
import json
import pickle
d = { 'field1': 'value1', 'field2': 2, }
json.dump(d,open("testjson.txt","w"))
print json.load(open("testjson.txt","r"))
pickle.dump(d,open("testpickle.txt","w"))
print pickle.load(open("testpickle.txt","r"))
它产生的输出是(正确处理字符串和整数):
{u'field2': 2, u'field1': u'value1'}
{'field2': 2, 'field1': 'value1'}
答案 11 :(得分:1)
所以,我遇到了同样的问题。猜猜Google的第一个结果是什么。
因为我需要将所有数据传递给PyGTK,所以unicode字符串对我来说也不是很有用。所以我有另一种递归转换方法。它实际上也需要类型安全的JSON转换 - json.dump()会保留任何非文字,比如Python对象。但是不会转换dict索引。
# removes any objects, turns unicode back into str
def filter_data(obj):
if type(obj) in (int, float, str, bool):
return obj
elif type(obj) == unicode:
return str(obj)
elif type(obj) in (list, tuple, set):
obj = list(obj)
for i,v in enumerate(obj):
obj[i] = filter_data(v)
elif type(obj) == dict:
for i,v in obj.iteritems():
obj[i] = filter_data(v)
else:
print "invalid object in data, converting to string"
obj = str(obj)
return obj
答案 12 :(得分:1)
使用hook(来自https://stackoverflow.com/a/33571117/558397)
支持Python2& 3import requests
import six
from six import iteritems
requests.packages.urllib3.disable_warnings() # @UndefinedVariable
r = requests.get("http://echo.jsontest.com/key/value/one/two/three", verify=False)
def _byteify(data):
# if this is a unicode string, return its string representation
if isinstance(data, six.string_types):
return str(data.encode('utf-8').decode())
# if this is a list of values, return list of byteified values
if isinstance(data, list):
return [ _byteify(item) for item in data ]
# if this is a dictionary, return dictionary of byteified keys and values
# but only if we haven't already byteified it
if isinstance(data, dict):
return {
_byteify(key): _byteify(value) for key, value in iteritems(data)
}
# if it's anything else, return it in its original form
return data
w = r.json(object_hook=_byteify)
print(w)
返回:
{'three': '', 'key': 'value', 'one': 'two'}
答案 13 :(得分:0)
def _parseJSON(self, obj):
if isinstance(obj, dict):
newobj = {}
for key, value in obj.iteritems():
key = str(key)
newobj[key] = self._parseJSON(value)
elif isinstance(obj, list):
newobj = []
for value in obj:
newobj.append(self._parseJSON(value))
elif isinstance(obj, unicode):
newobj = str(obj)
else:
newobj = obj
return newobj
答案 14 :(得分:0)
我有一个JSON字典作为字符串。键和值是unicode对象,如下例所示:
myStringDict = "{u'key':u'value'}"
我可以使用上面建议的byteify
函数,使用dict
将字符串转换为ast.literal_eval(myStringDict)
对象。
答案 15 :(得分:0)
这是一个用C编写的递归编码器: https://github.com/axiros/nested_encode
与json.loads相比,“平均”结构的性能开销约为10%。
python speed.py
json loads [0.16sec]: {u'a': [{u'b': [[1, 2, [u'\xd6ster..
json loads + encoding [0.18sec]: {'a': [{'b': [[1, 2, ['\xc3\x96ster.
time overhead in percent: 9%
使用此测试结构:
import json, nested_encode, time
s = """
{
"firstName": "Jos\\u0301",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "\\u00d6sterreich",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null,
"a": [{"b": [[1, 2, ["\\u00d6sterreich"]]]}]
}
"""
t1 = time.time()
for i in xrange(10000):
u = json.loads(s)
dt_json = time.time() - t1
t1 = time.time()
for i in xrange(10000):
b = nested_encode.encode_nested(json.loads(s))
dt_json_enc = time.time() - t1
print "json loads [%.2fsec]: %s..." % (dt_json, str(u)[:20])
print "json loads + encoding [%.2fsec]: %s..." % (dt_json_enc, str(b)[:20])
print "time overhead in percent: %i%%" % (100 * (dt_json_enc - dt_json)/dt_json)
答案 16 :(得分:0)
这是游戏的后期,但我建造了这个递归施法者。它适用于我的需求,我认为它相对完整。它可能对你有帮助。
def _parseJSON(self, obj):
newobj = {}
for key, value in obj.iteritems():
key = str(key)
if isinstance(value, dict):
newobj[key] = self._parseJSON(value)
elif isinstance(value, list):
if key not in newobj:
newobj[key] = []
for i in value:
newobj[key].append(self._parseJSON(i))
elif isinstance(value, unicode):
val = str(value)
if val.isdigit():
val = int(val)
else:
try:
val = float(val)
except ValueError:
val = str(val)
newobj[key] = val
return newobj
只需传递一个JSON对象:
obj = json.loads(content, parse_float=float, parse_int=int)
obj = _parseJSON(obj)
我将它作为类的私有成员,但您可以根据需要重新调整方法。
答案 17 :(得分:0)
查看this类似问题的回答,其中说明
u-前缀只表示您有一个Unicode字符串。当您真正使用该字符串时,它不会出现在您的数据中。不要被打印输出抛出。
例如,试试这个:
print mail_accounts[0]["i"]
你不会看到你。
答案 18 :(得分:0)
使用Python 3.6,有时我仍会遇到这个问题。例如,当从REST API获取响应并将响应文本加载到JSON时,我仍然获得unicode字符串。 使用json.dumps()找到了一个简单的解决方案。
createBackgroundUrl(imageName) {
return `url(assets/weatherBG/${imageName})`
}
答案 19 :(得分:-1)
我也遇到了这个问题,并且不得不处理JSON,我想出了一个将unicode键转换为字符串的小循环。 (GAE上的simplejson
不返回字符串键。)
obj
是从JSON解码的对象:
if NAME_CLASS_MAP.has_key(cls):
kwargs = {}
for i in obj.keys():
kwargs[str(i)] = obj[i]
o = NAME_CLASS_MAP[cls](**kwargs)
o.save()
kwargs
是我传递给GAE应用程序的构造函数(它不喜欢unicode
中的**kwargs
个键)
不像Wells的解决方案那么强大,但要小得多。
答案 20 :(得分:-1)
我已经调整了answer Mark Amery中的代码,特别是为了摆脱isinstance
鸭子打字的优点。
手动完成编码,并禁用ensure_ascii
。 json.dump
的python文档说明了
如果ensure_ascii为True(默认值),则输出中的所有非ASCII字符都使用\ uXXXX序列进行转义
免责声明:在doctest中我使用匈牙利语。一些值得注意的与匈牙利相关的字符编码是:cp852
使用的IBM / OEM编码。在DOS中(有时称为 ascii ,我认为错误,它取决于代码页设置),cp1250
使用例如。在Windows中(有时称为 ansi ,取决于区域设置)和iso-8859-2
,有时在http服务器上使用。测试文本Tüskéshátú kígyóbűvölő
归因于KoltaiLászló(原生个人姓名表单),来自wikipedia。
# coding: utf-8
"""
This file should be encoded correctly with utf-8.
"""
import json
def encode_items(input, encoding='utf-8'):
u"""original from: https://stackoverflow.com/a/13101776/611007
adapted by SO/u/611007 (20150623)
>>>
>>> ## run this with `python -m doctest <this file>.py` from command line
>>>
>>> txt = u"Tüskéshátú kígyóbűvölő"
>>> txt2 = u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"
>>> txt3 = u"uúuutifu"
>>> txt4 = b'u\\xfauutifu'
>>> # txt4 shouldn't be 'u\\xc3\\xbauutifu', string content needs double backslash for doctest:
>>> assert u'\\u0102' not in b'u\\xfauutifu'.decode('cp1250')
>>> txt4u = txt4.decode('cp1250')
>>> assert txt4u == u'u\\xfauutifu', repr(txt4u)
>>> txt5 = b"u\\xc3\\xbauutifu"
>>> txt5u = txt5.decode('utf-8')
>>> txt6 = u"u\\u251c\\u2551uutifu"
>>> there_and_back_again = lambda t: encode_items(t, encoding='utf-8').decode('utf-8')
>>> assert txt == there_and_back_again(txt)
>>> assert txt == there_and_back_again(txt2)
>>> assert txt3 == there_and_back_again(txt3)
>>> assert txt3.encode('cp852') == there_and_back_again(txt4u).encode('cp852')
>>> assert txt3 == txt4u,(txt3,txt4u)
>>> assert txt3 == there_and_back_again(txt5)
>>> assert txt3 == there_and_back_again(txt5u)
>>> assert txt3 == there_and_back_again(txt4u)
>>> assert txt3.encode('cp1250') == encode_items(txt4, encoding='utf-8')
>>> assert txt3.encode('utf-8') == encode_items(txt5, encoding='utf-8')
>>> assert txt2.encode('utf-8') == encode_items(txt, encoding='utf-8')
>>> assert {'a':txt2.encode('utf-8')} == encode_items({'a':txt}, encoding='utf-8')
>>> assert [txt2.encode('utf-8')] == encode_items([txt], encoding='utf-8')
>>> assert [[txt2.encode('utf-8')]] == encode_items([[txt]], encoding='utf-8')
>>> assert [{'a':txt2.encode('utf-8')}] == encode_items([{'a':txt}], encoding='utf-8')
>>> assert {'b':{'a':txt2.encode('utf-8')}} == encode_items({'b':{'a':txt}}, encoding='utf-8')
"""
try:
input.iteritems
return {encode_items(k): encode_items(v) for (k,v) in input.iteritems()}
except AttributeError:
if isinstance(input, unicode):
return input.encode(encoding)
elif isinstance(input, str):
return input
try:
iter(input)
return [encode_items(e) for e in input]
except TypeError:
return input
def alt_dumps(obj, **kwargs):
"""
>>> alt_dumps({'a': u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"})
'{"a": "T\\xc3\\xbcsk\\xc3\\xa9sh\\xc3\\xa1t\\xc3\\xba k\\xc3\\xadgy\\xc3\\xb3b\\xc5\\xb1v\\xc3\\xb6l\\xc5\\x91"}'
"""
if 'ensure_ascii' in kwargs:
del kwargs['ensure_ascii']
return json.dumps(encode_items(obj), ensure_ascii=False, **kwargs)
我还想强调引用answer的Jarret Hardie JSON spec,引用:
字符串是零个或多个Unicode字符的集合
在我的用例中,我有json的文件。它们是utf-8
个编码文件。 ensure_ascii
导致正确转义但不易读取的json文件,这就是为什么我改编了Mark Amery的答案以满足我的需求。
doctest不是特别贴心,但我分享了代码,希望它对某人有用。