JSON

2013-03-30 10 views
22

साथ अजगर tuples रक्षित मैं अभी भी एक छोटे से इस के लिए नया हूँ, इसलिए मैं चीजों के लिए सभी पारंपरिक दृष्टि से पता नहीं हो सकता है:JSON

यह अजगर tuples संरक्षित करने के लिए संभव है जब JSON साथ एन्कोडिंग है? अभी json.loads(json.dumps(tuple)) मुझे एक सूची वापस देता है। मैं अपने tuples सूचियों में कनवर्ट नहीं करना चाहता, लेकिन मैं JSON का उपयोग करना चाहता हूँ। तो, क्या विकल्प हैं?

कारण: मैं एक ऐप बना रहा हूं जो बहु-आयामी सरणी का उपयोग करता है, हमेशा एक ही आकार नहीं। मेरे पास कुछ क्लास विधियां हैं जो सरणी की जांच करने के लिए रिकर्सन का उपयोग करती हैं और एंडपॉइंट्स को स्ट्रिंग या इंट के रूप में डाली जाती हैं। मुझे हाल ही में एहसास हुआ कि (मेरा रिकर्सन कैसे काम करता है) के आधार पर मैं सरणी (पायथन कच्चे) की गहरी रिकर्सिव खोज को रोकने के लिए टुपल्स का उपयोग कर सकता हूं। यह ऐसी स्थितियों में आसान हो सकता है जहां मुझे पता है कि मुझे यकीन है कि मुझे अपने डेटा संरचनाओं में गहराई से जांच करने की आवश्यकता नहीं होगी।

उत्तर

19

आप एक उच्च specialzed एनकोडर और एक विकोडक हुक लिख सकते हैं: आप पर विचार कर नहीं कर रहे हैं के रूप में

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] 
      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)]] 
+1

अच्छा simplejson के साथ है।[Pymongo] के समान ही (https://github.com/mongodb/mongo-python-driver/blob/master/bson/json_util.py) करता है। पूरा होने के लिए, 'एनकोड' में 'dict' शाखा भी होनी चाहिए। – georg

+0

यही कारण है कि यह विशिष्ट है :) ओपी के सरणी में उनमें डिक्ट्स नहीं लगते हैं। –

+0

धन्यवाद! मुझे कोड पढ़ने के लिए एक मिनट लग गया, लेकिन मुझे यह मिल गया और यह वही है जो मुझे चाहिए। यही वही तरीका है कि मैं बहु-डी सरणी पर रिकर्सन कर रहा हूं। मैं अभी भी "जेसन" के बाहर हुक कर रहा हूं, हालांकि शायद मुझे 'object_hook' पर पढ़ना चाहिए। उदाहरण के लिए – mrKelley

16

नहीं, यह संभव नहीं है। जेएसओएन प्रारूप में एक टुपल की कोई अवधारणा नहीं है (JSON में किस प्रकार के अस्तित्व के संक्षिप्त ब्रेकडाउन के लिए here देखें)। पायथन का json मॉड्यूल पाइथन टुपल्स को जेएसओएन सूचियों में परिवर्तित करता है क्योंकि यह जेएसओएन में एक टपल के सबसे नज़दीकी चीज है।

आपने यहां अपने उपयोग के मामले का अधिक विवरण नहीं दिया है, लेकिन यदि आपको डेटा संरचनाओं के स्ट्रिंग प्रस्तुतियों को स्टोर करने की आवश्यकता है जिसमें टुपल्स शामिल हैं, तो कुछ संभावनाएं तुरंत दिमाग में आती हैं, जो आपके आधार पर उचित हो सकती है या नहीं भी हो सकती हैं स्थिति:

  1. अपनी खुद की एन्कोडिंग और डिकोडिंग कार्यों बनाएं
  2. उपयोग pickle (सावधान, pickle.loads उपयोगकर्ता द्वारा प्रदान की इनपुट पर उपयोग करने के लिए सुरक्षित नहीं है)।
  3. repr और json.dumps और json.loads के बजाय ast.literal_eval का उपयोग करें। repr आपको json.dumps पर उपस्थिति में उचित रूप से समान आउटपुट देगा, लेकिन repr टुपल्स को सूचियों में परिवर्तित नहीं करेगा। ast.literal_evaleval का एक कम शक्तिशाली, अधिक सुरक्षित संस्करण है जो केवल तार, संख्या, tuples, सूचियों, dicts, बूलियन, और None डीकोड करेगा।

विकल्प 3 शायद आपके लिए सबसे आसान और सरल समाधान है।

2

अजगर सूचियों और tuples के बीच सिद्धांत फर्क, अस्थिरता, जो JSON अभ्यावेदन के लिए अप्रासंगिक है है जब तक टेक्स्ट फॉर्म में JSON सूची के आंतरिक सदस्यों को संशोधित करना। बस उन सूचियों को चालू करें जिन्हें आप वापस टुपल्स में प्राप्त करते हैं। यदि आप किसी कस्टम ऑब्जेक्ट डिकोडर्स का उपयोग नहीं कर रहे हैं, तो केवल एक ही संरचित डेटाटाइप जिन्हें आप विचार करना चाहते हैं वह JSON ऑब्जेक्ट्स और एरेज़ हैं, जो पाइथन डिक्ट्स और सूचियों के रूप में बाहर आते हैं।

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 सरणियों अजगर सूचियों और दूसरों अजगर tuples होने के लिए होना चाहता हूँ रहे हैं, तो आप एक dict या टपल कि टाइप जानकारी annotates में डेटा आइटम रैप करने के लिए की आवश्यकता होगी। कुछ स्वयं सूची या टुपल (या कुछ अन्य पुनरावृत्त प्रकार) के आधार पर ब्रांचिंग की तुलना में एल्गोरिदम के नियंत्रण प्रवाह को प्रभावित करने का एक बेहतर तरीका है।

3

यह

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)