【问题标题】:How to decode JSON to str and not unicode in Python (2.6)? [duplicate]如何在 Python (2.6) 中将 JSON 解码为 str 而不是 unicode? [复制]
【发布时间】:2011-06-11 01:07:16
【问题描述】:

我有一个 JSON 格式的配置文件,其中包含一些字符串形式的变量(总是 ascii)。默认情况下,这些字符串被解码为 un​​icode,但由于我必须将这些变量传递给我的 Python C 扩展,所以我需要它们作为普通的 Python 字符串。目前我正在使用str(unicode) 来转换 JSON 字符串,但更优雅、更简洁的解决方案将不胜感激。

有没有办法使用自定义 JSONDecoder 或对象挂钩将默认翻译从字符串更改为 unicode?​​p>

【问题讨论】:

  • 是的,自定义 JSONDecoder 应该能够跳过从 str 到 Unicode 的解码并返回原始二进制字符串。
  • @Lennart Regebro 我试图这样做但失败了:我不得不复制-n-paste-extend 很多类和模块私有常量。有没有一种简单的方法来调整我看不到的 JSONDecoder?
  • @TryPyPy:Python 中没有模块私有常量之类的东西......
  • 天啊。我不知道什么样的大脑腐烂了,但如果你真的看我下面的代码(在我使它更理智之前),我表现得好像 _var + all 是不可理解的。哇,谢谢你打开我的眼睛,我无法解释这里发生了什么......
  • :-) 我查看了代码,但我不得不承认它很难覆盖......

标签: python json unicode


【解决方案1】:

如果您不愿意失去一些速度,则不会。如果稍微慢一点是可以的,您必须考虑使用普通的json.loads 并递归转换为str 可能更便宜,也可能更快。

话虽如此,如果您确实想要一个 loads,它返回的字符串非常糟糕 以接受通过扩展代码而不是本意,这是一个可能的结果(主要通过复制-n-粘贴进行扩展) 这太愚蠢了,感谢 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) 解决方案。
  • 抱歉吓到你了,Lennart 让我意识到得到你想要的东西要容易得多。
【解决方案2】:

查看对this question 的回复是否对您有帮助(在该问题中,提问者使用的是simplejson)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-16
    • 2014-04-03
    • 2019-07-26
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2022-01-21
    • 2013-08-08
    相关资源
    最近更新 更多