2

使用 json 和 jsonpickle 的组合(在 2.7 中)编写了以下两个函数,用于存储和检索任何 Python(内置或用户定义)对象

def save(kind, obj):
    pickled = jsonpickle.encode(obj)
    filename = DATA_DESTINATION[kind] \\returns file destination to store json
    if os.path.isfile(filename):
        open(filename, 'w').close()
    with open(filename, 'w') as f:
        json.dump(pickled, f)

def retrieve(kind):
    filename = DATA_DESTINATION[kind] \\returns file destination to store json
    if os.path.isfile(filename):
        with open(filename, 'r') as f:
            pickled = json.load(f)
            unpickled = jsonpickle.decode(pickled)
            print unpickled

我没有使用用户定义的对象测试这两个函数,但是当我尝试 save() 一个内置的字符串字典时,(即 {'Adam': 'Age 19', 'Bill', 'Age 32 '}),然后我检索相同的文件,我得到相同的 unicode 字典,{u'Adam': u'Age 19', u'Bill', u'Age 32'}。我以为 json/jsonpickle 默认编码为 utf-8,这是怎么回事?

[更新]:删除所有 jsonpickle 编码/解码不会影响输出,仍然是 unicode,似乎是 json 的问题?也许我做错了什么。

4

4 回答 4

9
import jsonpickle
import json

jsonpickle.set_preferred_backend('json')
jsonpickle.set_encoder_options('json', ensure_ascii=False)
print( jsonpickle.encode( { "value" : "значение"}) )

{“价值”:“значение”}

于 2017-07-21T10:41:41.620 回答
1

您可以在调用 load() 后对 unicode 字符串进行编码。

json.loads('"\\u79c1"').encode('utf-8')

现在你又有了一个正常的字符串。

于 2012-08-12T22:01:32.223 回答
0

我以为 json ... 默认编码为 utf-8,这是怎么回事?

不,它编码为 ASCII。它解码为unicode.

>>> json.dumps(u'私')
'"\\u79c1"'
>>> json.loads('"\\u79c1"')
u'\u79c1'
于 2012-08-12T21:18:42.993 回答
0

问题是 json 作为一种序列化格式,表达能力不够,无法承载有关字符串原始类型的信息。换句话说,如果你有一个 json 字符串a,你无法判断它是来自 python 字符串"a"还是来自 python unicode字符串u"a"

实际上,您可以阅读json 模块的文档中关于 option 的信息ensure_ascii。基本上,根据您要编写生成的 json 的位置,您可能会容忍一个 unicode 字符串,或者需要一个所有传入 unicode 字符正确转义的 ascii 字符串。

例如:

>>> import json
>>> json.dumps({'a':'b'})
'{"a": "b"}'
>>> json.dumps({'a':u'b'}, ensure_ascii=False)
u'{"a": "b"}'
>>> json.dumps({'a':u'b'})
'{"a": "b"}'
>>> json.dumps({u'a':'b'})
'{"a": "b"}'
>>> json.dumps({'a':u'\xe0'})
'{"a": "\\u00e0"}'
>>> json.dumps({'a':u'\xe0'}, ensure_ascii=False)
u'{"a": "\xe0"}'

如您所见,根据您的值,ensure_ascii您最终会得到一个 ascii json 字符串或 unicode 字符串,但原始对象的组件都被展平为相同的通用编码。特别看{"a": "b"}情况。

jsonpickle只是将json其用作其底层序列化引擎,不添加额外的元数据来跟踪原始字符串类型,因此您实际上在此过程中丢失了信息。

>>> jsonpickle.encode({'a': 'b'})
'{"a": "b"}'
>>> jsonpickle.encode({'a': u'b'})
'{"a": "b"}'
>>> jsonpickle.encode({u'a': 'b'})
'{"a": "b"}'
于 2012-08-13T09:59:57.443 回答