JSON অবজেক্টের আইটেমগুলি "json.dump" ব্যবহার করে ক্রম ছাড়ছে?


156

আমি json.dumpsjson মত রূপান্তর করতে ব্যবহার করছি

countries.append({"id":row.id,"name":row.name,"timezone":row.timezone})
print json.dumps(countries)

আমার ফলাফলটি হ'ল:

[
   {"timezone": 4, "id": 1, "name": "Mauritius"}, 
   {"timezone": 2, "id": 2, "name": "France"}, 
   {"timezone": 1, "id": 3, "name": "England"}, 
   {"timezone": -4, "id": 4, "name": "USA"}
]

আমি নিম্নলিখিত ক্রমে কীগুলি রাখতে চাই: আইডি, নাম, টাইমজোন - তবে পরিবর্তে আমার কাছে টাইমজোন, আইডি, নাম রয়েছে।

আমি কীভাবে এটি ঠিক করব?

উত্তর:


243

পাইথন dict(পাইথন ৩.7 এর পূর্বে) এবং জেএসওএন অবজেক্ট আনর্ডারড সংগ্রহ col sort_keysকীগুলি বাছাই করতে আপনি প্যারামিটারটি পাস করতে পারেন:

>>> import json
>>> json.dumps({'a': 1, 'b': 2})
'{"b": 2, "a": 1}'
>>> json.dumps({'a': 1, 'b': 2}, sort_keys=True)
'{"a": 1, "b": 2}'

আপনার যদি কোনও নির্দিষ্ট আদেশের প্রয়োজন হয়; আপনি ব্যবহারcollections.OrderedDict করতে পারেন :

>>> from collections import OrderedDict
>>> json.dumps(OrderedDict([("a", 1), ("b", 2)]))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict([("b", 2), ("a", 1)]))
'{"b": 2, "a": 1}'

পাইথন ৩.6 থেকে , মূল শব্দটি আর্গুমেন্ট অর্ডার সংরক্ষণ করা হয়েছে এবং উপরেরগুলি একটি ভাল সিনট্যাক্স ব্যবহার করে আবারও লেখা যেতে পারে:

>>> json.dumps(OrderedDict(a=1, b=2))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict(b=2, a=1))
'{"b": 2, "a": 1}'

পিইপি 468 দেখুন - কীওয়ার্ড আর্গুমেন্ট অর্ডার সংরক্ষণ করা

যদি আপনার ইনপুটটি JSON হিসাবে দেওয়া হয় তবে অর্ডার সংরক্ষণের জন্য (পেতে OrderedDict), আপনি পাস করতে পারেন object_pair_hook, @ ফ্রেড ইয়ানকোভস্কির পরামর্শ অনুসারে :

>>> json.loads('{"a": 1, "b": 2}', object_pairs_hook=OrderedDict)
OrderedDict([('a', 1), ('b', 2)])
>>> json.loads('{"b": 2, "a": 1}', object_pairs_hook=OrderedDict)
OrderedDict([('b', 2), ('a', 1)])

2
অর্ডারডিক্টের দীক্ষা সত্যিই কুৎসিত
জিন

3
@jean: প্রাথমিক মান কিছুই করার আছে OrderedDict(), আপনি একটি পাস করতে পারেন dictথেকে OrderedDict(), আপনি আদেশ জোড়া একটি তালিকা প্রেরণ করতে পারেন dict()খুব - যদিও অর্ডার এইসব ক্ষেত্রে উভয়ের মধ্যে হারিয়ে গেছে।
jfs

অর্ডার সংরক্ষণ করার সময় আমি এটির অর্থ চাইছি, অনেকগুলি '(' এবং ')' টাইপ করা দরকার
জিন


25
এছাড়াও, আপনি যদি JSON ব্যবহার করে লোড করেন তবে d = json.load(f, object_pairs_hook=OrderedDict)পরবর্তীতে json.dump(d)মূল উপাদানগুলির ক্রম ধরে রাখা হবে।
ফ্রেড ইয়াঙ্কোভস্কি

21

অন্যরা যেমন অন্তর্নিহিত ডিকটি বিন্যস্ত বলে উল্লেখ করেছেন। তবে পাইথনে অর্ডারডিক্ট অবজেক্ট রয়েছে। (সেগুলি সাম্প্রতিক অজগরগুলিতে নির্মিত হয়েছে, বা আপনি এটি ব্যবহার করতে পারেন: http://code.activestate.com/recips/576693/ )।

আমি বিশ্বাস করি যে নতুন অজগর জসন বাস্তবায়নগুলি অর্ডারডিক্টসে অন্তর্নির্মিতভাবে সঠিকভাবে পরিচালনা করে তবে আমি নিশ্চিত নই (এবং আমার কাছে পরীক্ষার সহজ অ্যাক্সেস নেই)।

পুরাতন পাইথনস সিম্পজন বাস্তবায়ন অর্ডারডিক্ট অবজেক্টগুলিকে সুন্দরভাবে পরিচালনা করতে পারে না এবং সেগুলি আউটপুট দেওয়ার আগে নিয়মিত ডিক্টে রূপান্তরিত করে .. তবে আপনি নিম্নলিখিতটি দ্বারা এটি কাটিয়ে উঠতে পারেন:

class OrderedJsonEncoder( simplejson.JSONEncoder ):
   def encode(self,o):
      if isinstance(o,OrderedDict.OrderedDict):
         return "{" + ",".join( [ self.encode(k)+":"+self.encode(v) for (k,v) in o.iteritems() ] ) + "}"
      else:
         return simplejson.JSONEncoder.encode(self, o)

এখন এটি ব্যবহার করে আমরা পাই:

>>> import OrderedDict
>>> unordered={"id":123,"name":"a_name","timezone":"tz"}
>>> ordered = OrderedDict.OrderedDict( [("id",123), ("name","a_name"), ("timezone","tz")] )
>>> e = OrderedJsonEncoder()
>>> print e.encode( unordered )
{"timezone": "tz", "id": 123, "name": "a_name"}
>>> print e.encode( ordered )
{"id":123,"name":"a_name","timezone":"tz"}

যা পছন্দসইভাবে অনেক বেশি।

অন্য বিকল্পটি হ'ল সরাসরি আপনার সারি শ্রেণিটি ব্যবহার করতে এনকোডারকে বিশেষীকরণ করা হবে এবং তারপরে আপনার কোনও মধ্যবর্তী ডিক বা আনর্ডারডিক্টের প্রয়োজন হবে না।


5
নোট করুন যে JSON অবজেক্টগুলি এখনও নিখরচায় রয়েছে ; কোনও জেএসওএন ক্লায়েন্ট অবজেক্টের সংজ্ঞাটি পড়তে এবং কীগুলির ক্রমটিকে সম্পূর্ণ উপেক্ষা করতে পারে এবং পুরোপুরি আরএফসি অনুগত হতে পারে।
মার্টিজন পিটারস

4
মার্টিজন সঠিক, এটি আরএফসি সম্মতিতে প্রভাব ফেলবে না, তবে আপনি যদি আপনার জেএসওএন-এর জন্য ধারাবাহিক বিন্যাস রাখতে চান তবে এটি অবশ্যই মূল্যবান হতে পারে (উদাহরণস্বরূপ, যদি ফাইলটি সংস্করণ নিয়ন্ত্রণে থাকে, বা কোনও মানব পাঠকের পক্ষে এটি সহজ করা যায়) আপনার ডকুমেন্টেশনের সাথে এন্ট্রি অর্ডার তৈরি করার বিষয়টি বুঝতে
মাইকেল অ্যান্ডারসন

3
যে ক্ষেত্রে আপনি কেবল কল sort_keysকরার Trueসময় সেট করেছেন json.dumps(); অর্ডার স্থিতিশীলতার জন্য (পরীক্ষার জন্য, স্থিতিশীল ক্যাশে বা ভিসিএস কমিট করে), বাছাই কী যথেষ্ট is
মার্টিজন পিটারস

7

অভিধানের ক্রমটির সংজ্ঞা দেওয়া ক্রমের সাথে কোনও সম্পর্ক নেই all এটি কেবল জাসনে পরিণত হওয়া নয়, সমস্ত অভিধানের ক্ষেত্রেই সত্য।

>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}

প্রকৃতপক্ষে, অভিধানটি পৌঁছানোর আগেই "উল্টোদিকে" পরিণত হয়েছিল json.dumps:

>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}

6

আরে আমি জানি এই উত্তরের জন্য এত দেরি হয়েছে তবে সাজ্ট_কিগুলি যুক্ত করুন এবং এটিতে মিথ্যা নির্ধারণ করুন:

json.dumps({'****': ***},sort_keys=False)

এটি আমার জন্য কাজ করেছে


4

json.dump () আপনার অভিধানের অর্ডার সংরক্ষণ করবে। একটি পাঠ্য সম্পাদকে ফাইলটি খুলুন এবং আপনি দেখতে পাবেন। আপনি অর্ডারডিক্ট প্রেরণ করেন না তা এটি অর্ডার সংরক্ষণ করবে the

তবে json.load () সংরক্ষণ করা অবজেক্টের ক্রম হারাবে যদি না আপনি এটি অর্ডারডিক্টে লোড করতে বলে থাকেন, যা জেএসবেসটিস্টিয়ানের নির্দেশ অনুসারে অবজেক্ট_পেইস_হুক প্যারামিটার দিয়ে সম্পন্ন হয়।

এটি অন্যথায় অর্ডারটি হারাবে কারণ সাধারণ ক্রিয়াকলাপের অধীনে, এটি সংরক্ষিত অভিধান অবজেক্টটিকে একটি নিয়মিত ডিকের মধ্যে লোড করে দেয় এবং একটি নিয়মিত ডিক এটি প্রদত্ত আইটেমগুলির গন্ধ সংরক্ষণ করে না।


লোডের উপর অর্ডার বজায় রাখা এটি ডাম্প টাইম অর্ডারিংয়ের যত্ন নেয় বলে এটি আসলে আরও ভাল সমাধান। এই উত্তরের জন্য ধন্যবাদ।
অরুণ আর

2

JSON এ, জাভাস্ক্রিপ্টের মতো, অবজেক্ট কীগুলির ক্রম অর্থহীন, সুতরাং তারা কোন অর্ডারে প্রদর্শিত হবে তা সত্যই আসে যায় না, এটি একই বস্তু।


(এবং এটি স্ট্যান্ডার্ড পাইথনের ক্ষেত্রেও সত্য dict)

12
তবে যেহেতু জেএসএন এটি বিশ্লেষণ না করা পর্যন্ত একটি স্ট্রিং প্রতিনিধিত্ব করে, স্ট্রিং তুলনা (যেমন ডক্টেসেটগুলিতে) এখনও ক্রমের প্রয়োজন হতে পারে। সুতরাং আমি বলব না এটি কখনই গুরুত্বপূর্ণ নয়।
মাইকেল স্কট কুথবার্ট

1
এটি জাভাস্ক্রিপ্ট (ইসিএমএ স্ক্রিপ্ট) স্ট্যান্ডার্ডের ক্ষেত্রে সত্য হলেও, সমস্ত বাস্তবায়নগুলি (স্ট্রিং) কীগুলি উত্স অনুসারে রাখে।
thejjorn

1
@ পলপ্রো সত্যিই? কোনটি? আমি জানি ক্রোম একবার এখানে স্ট্যান্ডার্ড অনুসরণ করার চেষ্টা করেছিল, তবে জমা দেওয়ার জন্য কোডড হয়েছিল ( কোড . google.com/p/v8/issues/detail?id=164 )। আমি ভাবিনি যে এর পরেও কেউ একই জিনিস চেষ্টা করবে ...
thebjorn

2
@ পলপ্রো আপনি ওপির প্রশ্নটিকে সঠিকভাবে সম্বোধন করছেন। তবে আমি যুক্ত করতে চাই যে অর্ডার সংরক্ষণের জন্য বৈধ ব্যবহার রয়েছে। উদাহরণস্বরূপ, কেউ এমন স্ক্রিপ্ট লিখতে পারে যা জেএসএন পড়ে, কিছু রূপান্তর প্রয়োগ করে এবং ফলাফলগুলি আবার লিখে দেয়। আপনি অর্ডার সংরক্ষণ করা চাইবেন যাতে কোনও ডিফ সরঞ্জাম স্পষ্টভাবে পরিবর্তনগুলি দেখায়।
পল রাদেমাচার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.