我使用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`
(2017年一个简单而干净的解决方案是使用最新版本的Python——即Python 3和更高版本。)
有一个简单的变通办法。
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字符串时,这就变得更麻烦了。完整的答案很快就变得棘手起来。
有一个简单的变通办法。
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字符串时,这就变得更麻烦了。完整的答案很快就变得棘手起来。
我也遇到了同样的问题。
因为我需要将所有数据传递给PyGTK,所以Unicode字符串对我来说也不是很有用。这是另一种递归转换方法。实际上,类型安全的JSON转换也需要它——JSON .dump()会放弃任何非字面量,比如Python对象。但是它不转换字典索引。
# 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
没有内置选项让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中获得的输出上调用此函数。加载或json。负载的电话。
几点注意事项:
To support Python 2.6 or earlier, replace return {byteify(key): byteify(value) for key, value in input.iteritems()} with return dict([(byteify(key), byteify(value)) for key, value in input.iteritems()]), since dictionary comprehensions weren't supported until Python 2.7.
Since this answer recurses through the entire decoded object, it has a couple of undesirable performance characteristics that can be avoided with very careful use of the object_hook or object_pairs_hook parameters. Mirec Miskuf's answer is so far the only one that manages to pull this off correctly, although as a consequence, it's significantly more complicated than my approach.
只需使用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'}