如何在Python(2.6)中将JSON解码为字符串而不是Unicode?

9
我有一个JSON格式的配置文件,其中包含几个字符串变量(始终为ASCII码)。这些字符串默认情况下会被解码为Unicode,但由于我必须将这些变量传递给Python C扩展程序,所以需要它们作为普通的Python字符串。目前,我正在使用 str(unicode) 来转换JSON字符串,但更优雅、更简洁的解决方案将受到欢迎。
是否有一种方法可以通过自定义JSONDecoder或对象钩子来更改从字符串到Unicode的默认转换方式?

是的,自定义的JSONDecoder应该能够跳过从str到Unicode的解码并返回原始二进制字符串。 - Lennart Regebro
@Lennart Regebro 我尝试过了,但失败了:我不得不复制粘贴扩展很多类和模块私有常量。有没有一种简单的方法可以调整JSONDecoder,而我却看不到呢? - TryPyPy
@TryPyPy:Python 中不存在模块私有常量这样的东西... - Lennart Regebro
天啊,我不知道我脑子怎么了,但如果你看一下我的代码(在我让它变得更加合理之前),我好像把 _var + all 当作是不可透过的东西。哇,感谢你让我开了眼界,我无法解释这里发生了什么... - TryPyPy
我看了一下代码,不得不承认它确实很难覆盖... - Lennart Regebro
导入json foo = "{'bar': 'baz'}" json.loads(foo, 'ascii') - lehins
2个回答

1

如果你不想失去一些速度,那就不要这样做。如果稍微慢一点没关系,你需要考虑使用普通的json.loads并递归转换为str可能更便宜,也许更快。

话虽如此,如果你真的非常想要一个返回字符串的loads,以至于愿意接受通过扩展不打算使用的代码来实现,这里有一个可能的结果(大部分是通过复制粘贴进行扩展)这是荒谬的,感谢Lennart让我看到了光明(即,你只需要扩展JSONDecoder和一些技巧):

import json
from json import decoder, scanner

from json.scanner import make_scanner
from _json import scanstring as c_scanstring

_CONSTANTS = json.decoder._CONSTANTS

py_make_scanner = scanner.py_make_scanner

# Convert from unicode to str
def str_scanstring(*args, **kwargs):
    result = c_scanstring(*args, **kwargs)
    return str(result[0]), result[1]

# Little dirty trick here
json.decoder.scanstring = str_scanstring

class StrJSONDecoder(decoder.JSONDecoder):
    def __init__(self, encoding=None, object_hook=None, parse_float=None,
            parse_int=None, parse_constant=None, strict=True,
            object_pairs_hook=None):
        self.encoding = encoding
        self.object_hook = object_hook
        self.object_pairs_hook = object_pairs_hook
        self.parse_float = parse_float or float
        self.parse_int = parse_int or int
        self.parse_constant = parse_constant or _CONSTANTS.__getitem__
        self.strict = strict
        self.parse_object = decoder.JSONObject
        self.parse_array = decoder.JSONArray
        self.parse_string = str_scanstring
        self.scan_once = py_make_scanner(self)

# And another little dirty trick there    
_default_decoder = StrJSONDecoder(encoding=None, object_hook=None,
                               object_pairs_hook=None)

json._default_decoder = _default_decoder

j = {1:'2', 1.1:[1,2,3], u'test': {12:12, 13:'o'}}
print json.loads(json.dumps(j))

感谢您详细的回答。我现在意识到,我想要的东西之所以不被支持是有原因的,所以我将坚持使用str(unicode)解决方案。 - Adrian
很抱歉吓到您,Lennart让我意识到获取您想要的东西要容易得多。 - TryPyPy

0

看看这个问题的回答是否对你有帮助(在那个问题中,提问者正在使用simplejson)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接