পাইথনের জসন মডিউল, ডিকশনারী কীগুলিকে স্ট্রিংয়ে রূপান্তর করে


130

আমি খুঁজে পেয়েছি যে নিম্নলিখিতটি যখন চালানো হয়, তখন পাইথনের জসন মডিউল (২.6 সাল থেকে অন্তর্ভুক্ত) ইনট্রিকশন কীগুলিকে স্ট্রিংয়ে রূপান্তর করে।

>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'

ডাম্প এবং লোডের উপর স্ট্রিংকে পার্স করার প্রয়োজন ছাড়াই কোনও কী হিসাবে কোন কী হিসাবে কোনও int হিসাবে সংরক্ষণ করা যায়? আমি বিশ্বাস করি যে এটি জাসন মডিউল দ্বারা সরবরাহিত হুকগুলি ব্যবহার করে সম্ভব হবে, তবে এটির জন্য এখনও পার্সিং প্রয়োজন। আমি সম্ভবত উপেক্ষা করা একটি যুক্তি আছে? চিয়ার্স, চ্যাজ

উপ-প্রশ্ন: উত্তরের জন্য ধন্যবাদ। আমার আশঙ্কা মত জসন কাজ করে দেখছে, ডাম্পগুলির আউটপুট বিশ্লেষণ করে কী প্রকারটি বোঝানোর সহজ উপায় কি আছে? এছাড়াও আমার ডাম্পিংয়ের কোডটি কোড এবং কোনও সার্ভার থেকে জেসন অবজেক্ট ডাউনলোড করা এবং এটি লোড করা কোড দুটি নোট করা উচিত both


23
json কীগুলিতে স্ট্রিং থাকতে হবে
টোনফা

উত্তর:


86

বিভিন্ন ম্যাপিং সংগ্রহের মধ্যে সূক্ষ্ম পার্থক্যের মধ্যে এটি একটি যা আপনাকে কামড়াতে পারে। JSON কীগুলি স্ট্রিং হিসাবে বিবেচনা করে; পাইথন স্বতন্ত্র কীগুলিকে সমর্থন করে যা কেবলমাত্র টাইপ করে।

পাইথনে (এবং স্পষ্টতই লুয়ায়) ম্যাপিংয়ের কীগুলি (যথাক্রমে অভিধান বা টেবিল,) বস্তুর উল্লেখ। পাইথনগুলিতে এগুলি অবশ্যই অপরিবর্তনীয় প্রকারের হতে পারে, বা এগুলি অবশ্যই কোনও বস্তু হতে পারে যা কোনও __hash__পদ্ধতি প্রয়োগ করে । (লুয়া ডকস প্রস্তাব দেয় যে এটি স্বয়ংক্রিয়ভাবে পরিবর্তিত বস্তুর জন্য হ্যাশ / কী হিসাবে অবজেক্টের আইডি ব্যবহার করে এবং একই বস্তুর সমতুল্য স্ট্রিং ম্যাপটি নিশ্চিত করতে স্ট্রিং ইন্টার্নিংয়ের উপর নির্ভর করে)।

পার্ল, জাভাস্ক্রিপ্ট, আর্ক এবং অন্যান্য অনেক ভাষায় হ্যাশগুলির জন্য কী, এসোসিয়েটিভ অ্যারে বা প্রদত্ত ভাষার জন্য যা কিছু বলা হয় সেগুলি স্ট্রিং (বা পার্লের "স্কেলার")। পার্লে $foo{1}, $foo{1.0}, and $foo{"1"}সমস্ত একই ম্যাপিংয়ের জন্য উল্লেখ রয়েছে %foo--- কীটি স্কেলার হিসাবে মূল্যায়ন করা হয়!

JSON একটি জাভাস্ক্রিপ্ট সিরিয়ালাইজেশন প্রযুক্তি হিসাবে শুরু হয়েছিল। (তাদেরকে JSON ঘোরা জে আভা এস cript হে bject এন otation।) স্বাভাবিকভাবেই এটা যা তার ম্যাপিং শব্দার্থবিদ্যা সঙ্গে সামঞ্জস্যপূর্ণ হয় তার ম্যাপিং স্বরলিপি জন্য শব্দার্থবিদ্যা প্রয়োগ করা হয়।

যদি আপনার সিরিয়ালের উভয় প্রান্তটি পাইথন হতে চলেছে তবে আপনি আচার ব্যবহার করা ভাল। আপনি যদি সত্যিই এটিকে জেএসওএন থেকে নেটিভ পাইথন অবজেক্টে রূপান্তর করতে চান তবে আমার ধারণা আপনার কাছে কয়েকটি পছন্দ আছে। প্রথমে আপনি চেষ্টা করতে পারেন ( try: ... except: ...) অভিধানে ব্যর্থতার ক্ষেত্রে কোনও কী কোনও সংখ্যায় রূপান্তর করতে। বিকল্পভাবে, আপনি যদি অন্য প্রান্তে কোড যুক্ত করেন (এই জেএসএন ডেটার ক্রমিক বা জেনারেটর) তবে আপনি এটি প্রতিটি মূল মানগুলিতে একটি জেএসওএন সিরিয়ালাইজেশন করতে পারেন --- কীগুলির তালিকা হিসাবে সরবরাহ করে providing (তারপরে আপনার পাইথন কোডটি কীগুলির তালিকার উপরে প্রথমে পুনরাবৃত্তি করবে, সেগুলি স্থানীয় পাইথন অবজেক্টগুলিতে তাত্ক্ষণিকভাবে / ডিসসায়ালাইজ করে ... এবং ম্যাপিংয়ের বাইরে মানগুলি অ্যাক্সেসের জন্য সেগুলি ব্যবহার করবে)।


1
তার জন্য ধন্যবাদ. দুর্ভাগ্যক্রমে আমি পিকল ব্যবহার করতে পারি না তবে তালিকার সাথে আপনার ধারণাটি দুর্দান্ত। এটি এখন বাস্তবায়ন করবে, ধারণার জন্য চিয়ার্স করুন।
চার্লস রিচি

1
(প্রসঙ্গক্রমে, পাইথন 1, 1 এল (দীর্ঘ পূর্ণসংখ্যার) এবং একই কীটিতে 1.0 মানচিত্র; তবে "1" (একটি স্ট্রিং) 1 (পূর্ণসংখ্যা) বা 1.0 (ভাসা) বা 1 এল (দীর্ঘ পূর্ণসংখ্যার মতো মানচিত্র দেয় না) )।
জিম ডেনিস

5
পিকল ব্যবহারের পরামর্শের সাথে সতর্ক থাকুন। পিকলের ফলে নির্বিচারে কোড কার্যকর করা যেতে পারে, সুতরাং আপনি ডিজিটালাইজ করছেন এমন ডেটার উত্স যদি অন্তর্নিহিত বিশ্বাসযোগ্য না হয়, আপনার জেএসএনের মতো একটি "নিরাপদ" সিরিয়ালাইজেশন প্রোটোকলের সাথে লেগে থাকা উচিত। এছাড়াও মনে রাখবেন যে প্রকল্পগুলির পরিধিটি প্রসারিত হওয়ার সাথে সাথে, কখনও কখনও এমন ফাংশনগুলি যা আপনি প্রত্যাশা করেছিলেন কেবলমাত্র নির্ভরযোগ্য ইনপুটটি ব্যবহারকারী সরবরাহ করা ইনপুট পাওয়া শুরু করবে এবং সুরক্ষার বিবেচনাগুলি সর্বদা পুনর্বিবেচিত হয় না।
অ্যাসিভ

56

না, জাভাস্ক্রিপ্টে নম্বর কী হিসাবে তেমন কোনও জিনিস নেই। সমস্ত বস্তুর বৈশিষ্ট্য স্ট্রিংয়ে রূপান্তরিত হয়।

var a= {1: 'a'};
for (k in a)
    alert(typeof k); // 'string'

এটি কিছু কৌতূহলোদ্দীপক আচরণগুলি হতে পারে:

a[999999999999999999999]= 'a'; // this even works on Array
alert(a[1000000000000000000000]); // 'a'
alert(a['999999999999999999999']); // fail
alert(a['1e+21']); // 'a'

জাভাস্ক্রিপ্ট অবজেক্টগুলি সত্যই সঠিক ম্যাপিংস নয় কারণ আপনি পাইথনের মতো ভাষায় এটি বুঝতে পছন্দ করেছেন এবং কীগুলি ব্যবহার করছেন যা স্ট্রিংয়ের কারণে উদ্ভট নয় in এ কারণেই জেএসওএন সর্বদা স্পষ্টভাবে স্ট্রিং হিসাবে কীগুলি লিখেন, এমনকি যেখানে এটি প্রয়োজনীয় মনে হয় না।


1
কেন 999999999999999999999রূপান্তর হয় না '999999999999999999999'?
পাইওটার ডব্রোগোস্ট

4
@ পাইওটারডব্রোগস্ট জাভাস্ক্রিপ্ট (অনেক ভাষার মতো) ইচ্ছামত-বিশাল সংখ্যক সঞ্চয় করতে পারে না। Numberটাইপ একটি হল আইইইই 754 ডবল ফ্লোটিং পয়েন্ট মান: আপনি অংশক 53 বিট পেতে, তাই আপনি 2⁵³ (9007199254740992) পূর্ণসংখ্যা সঠিকতা সঙ্গে পর্যন্ত সঞ্চয় করতে পারেন; এর বাইরে পূর্ণসংখ্যাগুলি অন্যান্য মানগুলিতে গোল হয়ে যাবে (সুতরাং 9007199254740993 === 9007199254740992)। 99999999999999999999999 রাউন্ড 100000000000000000000000000, যার জন্য ডিফল্ট toStringউপস্থাপনা 1e+21

22

বিকল্পভাবে আপনি জসন ব্যবহার করে এনকোডিং করার সময় অভিধানটিকে [(কে 1, ভি 1), (কে 2, ভি 2)] ফর্ম্যাটের একটি তালিকাতে রূপান্তর করার চেষ্টা করতে পারেন এবং ডিকোডিংয়ের পরে এটিকে আবার অভিধানে রূপান্তর করতে চেষ্টা করতে পারেন।


>>>> import json
>>>> json.dumps(releases.items())
    '[[1, "foo-v0.1"]]'
>>>> releases = {1: "foo-v0.1"}
>>>> releases == dict(json.loads(json.dumps(releases.items())))
     True
আমি বিশ্বাস করি যে জেসন থেকে ডিকোডিংয়ের পরে সমস্ত পরামিতিগুলি অভিধানে রূপান্তরিত করতে হবে তা চিহ্নিত করার জন্য এর জন্য কিছু ধরণের পতাকা থাকা দরকার flag


নেস্টেড ডিক অবজেক্ট ছাড়াই ডিক অবজেক্টের জন্য ভাল সমাধান!
টম ইউ

15

আপনার অনুমানের জবাব দেওয়া:

এটি ব্যবহার করে সম্পন্ন করা যেতে পারে json.loads(jsonDict, object_hook=jsonKeys2int)

def jsonKeys2int(x):
    if isinstance(x, dict):
            return {int(k):v for k,v in x.items()}
    return x

এই ফাংশনটি নেস্টেড ডিক্টসগুলির জন্যও কাজ করবে এবং ডিক বোঝার ব্যবহার করবে।

আপনি যদি মানগুলিও কাস্ট করতে চান তবে ব্যবহার করুন:

def jsonKV2int(x):
    if isinstance(x, dict):
            return {int(k):(int(v) if isinstance(v, unicode) else v) for k,v in x.items()}
    return x

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

উভয় ফাংশনটি (এবং মানগুলি) পূর্ণসংখ্যা হিসাবে ধরে নিয়েছে।

ধন্যবাদ:

/ / অভিধান অভিধানে যদি অন্য কীভাবে ব্যবহার করবেন?

একটি অভিধানে স্ট্রিং কী রূপান্তর করুন


এই দুর্দান্ত ছিল। আমার ক্ষেত্রে পিকিং ব্যবহার করা যাবে না তাই আমি জেএসএন ব্যবহার করে কোনও বাইট_আররে রূপান্তর করার মাধ্যমে কোনও জিনিসের সাহস সঞ্চয় করছি যাতে আমি সংকোচন ব্যবহার করতে পারি। আমি মিশ্র কীগুলি পেয়েছি, সুতরাং যখন কীটি কোনও আন্তঃরূপে রূপান্তরিত হয় না তখন একটি ভ্যালুআরারের বিষয়টি উপেক্ষা করার জন্য আমি আপনার উদাহরণটি পরিবর্তন করেছি
মিনিলিমনিম

11

আমি একই সমস্যা দ্বারা কামড়েছি। অন্যরা যেমন উল্লেখ করেছে, জেএসএনে, ম্যাপিং কীগুলি অবশ্যই স্ট্রিং হওয়া উচিত। আপনি দুটি কাজের একটি করতে পারেন। আপনি কম কড়া জেএসএন লাইব্রেরি যেমন ডেমজসন ব্যবহার করতে পারেন যা পূর্ণসংখ্যার স্ট্রিংগুলিকে মঞ্জুরি দেয়। যদি অন্য কোনও প্রোগ্রাম (বা অন্য ভাষায় অন্য কোনও) এটি পড়তে চলেছে, তবে আপনার ঠিক আছে। অথবা আপনি আলাদা সিরিয়ালাইজেশন ভাষা ব্যবহার করতে পারেন। আমি আচার পরামর্শ দেব না। এটি পড়া শক্ত, এবং এটি সুরক্ষিত হওয়ার জন্য ডিজাইন করা হয়নি । পরিবর্তে, আমি YAML, যা (প্রায়) JSON এর সুপারস্টার, এবং পূর্ণসংখ্য কীগুলি মঞ্জুরি দেয় suggest (কমপক্ষে পাইওয়ামএল করেন))


2

ব্যবহার str(dict)করে অভিধানটিকে স্ট্রিং হিসাবে রূপান্তর করুন এবং তারপরে এটি ডিকটিতে আবার রূপান্তর করুন:

import ast
ast.literal_eval(string)

1

এখানে আমার সমাধান! আমি ব্যবহার করেছি object_hook, যখন আপনি বাসা বেঁধেছেন তা কার্যকরjson

>>> import json
>>> json_data = '{"1": "one", "2": {"-3": "minus three", "4": "four"}}'
>>> py_dict = json.loads(json_data, object_hook=lambda d: {int(k) if k.lstrip('-').isdigit() else k: v for k, v in d.items()})

>>> py_dict
{1: 'one', 2: {-3: 'minus three', 4: 'four'}}

কেবলমাত্র ইনস থেকে জসন কী পার্স করার জন্য ফিল্টার রয়েছে। আপনি int(v) if v.lstrip('-').isdigit() else vjson মান জন্য ফিল্টার ব্যবহার করতে পারেন ।


1

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

def convert_keys_to_int(d: dict):
    new_dict = {}
    for k, v in d.items():
        try:
            new_key = int(k)
        except ValueError:
            new_key = k
        if type(v) == dict:
            v = _convert_keys_to_int(v)
        new_dict[new_key] = v
    return new_dict

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

>>>d = {1: 3, 2: 'a', 3: {1: 'a', 2: 10}, 4: {'a': 2, 'b': 10}}
>>>convert_keys_to_int(json.loads(json.dumps(d)))  == d
True

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.