使用JSON保留Python元组

mrK*_*ley 26 python json tuples

我对此仍然有点新意,所以我可能不知道所有传统的术语:

使用JSON编码时是否可以保留Python元组?现在json.loads(json.dumps(tuple))给我一个清单.我不想将我的元组转换为列表,但我想使用JSON.那么,有选择吗?

原因是:我正在创建一个使用多维数组的应用程序,并不总是相同的形状.我有一些类方法使用递归来探测数组并将端点转换为字符串或int.我最近意识到(基于我的递归如何工作)我可以使用元组来防止更深入的数组递归搜索(Python rawks).在我知道我肯定不需要深入研究数据结构的情况下,这可能会派上用场.

Pav*_*sov 30

您可以编写高度专业化的编码器和解码器钩子:

import json

class MultiDimensionalArrayEncoder(json.JSONEncoder):
    def encode(self, obj):
        def hint_tuples(item):
            if isinstance(item, tuple):
                return {'__tuple__': True, 'items': item}
            if isinstance(item, list):
                return [hint_tuples(e) for e in item]
            if isinstance(item, dict):
                return {key: hint_tuples(value) for key, value in item.items()}
            else:
                return item

        return super(MultiDimensionalArrayEncoder, self).encode(hint_tuples(obj))

def hinted_tuple_hook(obj):
    if '__tuple__' in obj:
        return tuple(obj['items'])
    else:
        return obj


enc = MultiDimensionalArrayEncoder()
jsonstring =  enc.encode([1, 2, (3, 4), [5, 6, (7, 8)]])

print jsonstring

# [1, 2, {"items": [3, 4], "__tuple__": true}, [5, 6, {"items": [7, 8], "__tuple__": true}]]

print json.loads(jsonstring, object_hook=hinted_tuple_hook)

# [1, 2, (3, 4), [5, 6, (7, 8)]]
Run Code Online (Sandbox Code Playgroud)

  • 好的。与 [pymongo](https://github.com/mongodb/mongo-python-driver/blob/master/bson/json_util.py) 的做法非常相似。为了完整起见,“encode”中还应该有“dict”分支。 (2认同)
  • 例如,似乎没有工作((1,2),3).替换`return {'__tuple__':True,'items':item}`with`return {'__tuple__':True,'items':tuple(hint_tuples(e)for e in item)}``maybe? (2认同)

Mar*_*ery 19

不,这是不可能的.JSON格式中没有元组的概念(有关JSON中存在的类型的简要分析,请参见此处).Python的json模块将Python元组转换为JSON列表,因为这是JSON中最接近元组的东西.

您没有在此处详细说明您的用例,但如果您需要存储包含元组的数据结构的字符串表示,则会立即想到一些可能性,根据您的具体情况,这些可能适合或不适合:

  1. 创建自己的编码和解码功能
  2. 使用泡菜(小心; pickle.loads在用户提供的输入上使用是不安全的).
  3. 使用reprast.literal_eval不是json.dumpsjson.loads.repr会给你输出相当类似的输出json.dumps,但repr不会将元组转换为列表.ast.literal_eval是一个功能较弱,更安全的版本,eval它只能解码字符串,数字,元组,列表,字符串,布尔值和None.

选项3可能是最简单,最简单的解决方案.

  • @ThomasKimber 嘿。鉴于 JSON 是“JavaScript object notation”的缩写,*PyON*(“Python Object Notation”的缩写)似乎是一个更好的名字——你的“PSON”建议听起来像是有一些名为 PythonScript 的语言。如果我可以打个响指,让 PyON 成为一个公认的术语,我会的,但不幸的是,我没有像 Crockford 这样的思想领袖那样的影响力。;) (2认同)

小智 5

python列表和元组之间的主要区别是可变性,与JSON表示形式无关,只要您不打算以文本形式修改JSON列表的内部成员。您可以将返回的列表变成元组。如果您不使用任何自定义对象解码器,那么您唯一需要考虑的结构化数据类型就是JSON对象和数组,它们以python dict和list的形式出现。

def tuplify(listything):
    if isinstance(listything, list): return tuple(map(tuplify, listything))
    if isinstance(listything, dict): return {k:tuplify(v) for k,v in listything.items()}
    return listything
Run Code Online (Sandbox Code Playgroud)

如果您专门进行解码,或者希望某些JSON数组成为python列表,而另一些则成为python元组,则需要将数据项包装在注释类型信息的dict或tuple中。与根据某个对象是列表还是元组(或其他某种可迭代类型)进行分支相比,这本身是一种影响算法控制流程的更好方法。

  • “原理区别”-->“主要区别”“文本形式”-->“文本形式” (2认同)