51

私はまだこれに少し慣れていないので、物事の従来の用語をすべて知っているわけではないかもしれません:

JSONでエンコードするときにPythonタプルを保持することは可能ですか? 今すぐjson.loads(json.dumps(tuple))リストを返してくれます。タプルをリストに変換したくありませんが、JSON を使用したいと考えています。それで、オプションはありますか?

理由: 常に同じ形状ではない、多次元配列を使用するアプリを作成しています。再帰を使用して配列をプローブし、エンドポイントを文字列または int としてキャストするクラス メソッドがいくつかあります。私は最近、(再帰の仕組みに基づいて)タプルを使用して、配列(Python rawks)のより深い再帰的検索を防ぐことができることに気付きました。これは、データ構造をこれ以上詳しく調査する必要がないことが確実にわかっている状況で役立ちます。

4

5 に答える 5

33

高度に専門化されたエンコーダーとデコーダー フックを作成できます。

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)]]
于 2013-03-30T17:58:24.290 に答える
24

いいえ、それは不可能です。JSON 形式にはタプルの概念はありません (JSONに存在する型の簡潔な内訳については、こちらを参照してください)。Python のjsonモジュールは、Python タプルを JSON リストに変換します。これは、JSON で最もタプルに近いものだからです。

ここではユースケースの詳細をあまり説明していませんが、タプルを含むデータ構造の文字列表現を保存する必要がある場合は、いくつかの可能性がすぐに思い浮かびます。状況に応じて適切な場合とそうでない場合があります。

  1. 独自のエンコードおよびデコード関数を作成する
  2. pickleを使用します(注意してください。pickle.loadsユーザー提供の入力で使用するのは安全ではありません)。
  3. reprast.literal_evalの代わりにjson.dumpsとを使用しjson.loadsます。reprと見た目がかなり似た出力が得られますがjson.dumpsreprタプルはリストに変換されません。ast.literal_evalは、eval文字列、数値、タプル、リスト、辞書、ブール値、およびNone.

オプション 3 は、おそらく最も簡単でシンプルなソリューションです。

于 2013-03-30T17:32:04.257 に答える
5

Python リストとタプルの主な違いは可変性です。これは、テキスト形式の JSON リストの内部メンバーを変更することを考えていない限り、JSON 表現とは無関係です。取得したリストをタプルに戻すことができます。カスタム オブジェクト デコーダーを使用していない場合、考慮する必要がある唯一の構造化データ型は JSON オブジェクトと配列であり、Python の辞書とリストとして出力されます。

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

デコードを特殊化している場合、または一部の JSON 配列を python リストにし、他のものを python タプルにしたい場合は、型情報に注釈を付ける dict または tuple でデータ項目をラップする必要があります。これ自体は、何かがリストかタプル (またはその他の反復可能な型) であるかに基づいて分岐するよりも、アルゴリズムの制御フローに影響を与えるためのより良い方法です。

于 2014-08-13T19:41:52.980 に答える
4

それはsimplejsonで

import simplejson

def _to_json(python_object) :
    if isinstance(python_object, tuple) :
        python_object = {'__class__': 'tuple',
                         '__value__': list(python_object)}
    else :
        raise TypeError(repr(python_object) + ' is not JSON serializable') 

    return python_object

def _from_json(json_object):                                   
    if json_object['__class__'] == 'tuple':
        return tuple(json_object['__value__'])
    return json_object


jsn = simplejson.dumps((1,2,3), 
                       default=_to_json, 
                       tuple_as_array=False)

tpl = simplejson.loads(jsn, object_hook=_from_json)
于 2015-04-28T02:09:21.217 に答える