Json.Unmarshal বনাম json.NewDecoder.Decode ব্যবহার করে ডিকোডিং JSON


201

আমি একটি এপিআই ক্লায়েন্ট বিকাশ করছি যেখানে আমাকে অনুরোধে একটি জেএসএন পেডলড এনকোড করতে হবে এবং প্রতিক্রিয়া থেকে একটি জেএসএন বডি ডিকোড করতে হবে।

আমি বেশ কয়েকটি লাইব্রেরি থেকে উত্স কোডটি পড়েছি এবং যা দেখেছি তা থেকে আমার কাছে জেএসএন স্ট্রিংটিকে এনকোডিং এবং ডিকোড করার জন্য মূলত দুটি সম্ভাবনা রয়েছে।

json.Unmarshalসম্পূর্ণ প্রতিক্রিয়া স্ট্রিং উত্তরণ ব্যবহার করুন

data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
    err = json.Unmarshal(data, value)
}

বা ব্যবহার json.NewDecoder.Decode

err = json.NewDecoder(resp.Body).Decode(value)

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

তদুপরি, এই প্রশ্ন থেকে গৃহীত উত্তর বলে

json.Decoderপরিবর্তে ব্যবহার করুন json.Unmarshal

তবে এর কারণ উল্লেখ করা হয়নি। আমি কি সত্যিই ব্যবহার এড়ানো উচিত json.Unmarshal?


গিটহাবের এই টান অনুরোধটি উম্মশালকে json.NewDecoder দিয়ে একটি কলকে প্রতিস্থাপন করেছে "JSON ডিকোডিংয়ের বাফার অপসারণ করতে"।
ম্যাট

এটি কেবল আপনার ব্যবহারের জন্য কী ইনপুটটি বেশি সুবিধাজনক তা নির্ভর করে। blog.golang.org/json-and-go উভয় কৌশল ব্যবহারের উদাহরণ দেয়।
রেফপোসাদাস

15
আইএমও, ioutil.ReadAllহয় প্রায় সবসময় করতে ভুল জিনিস। এটি আপনার লক্ষ্যের সাথে সম্পর্কিত নয়, তবে পাইপ থেকে নেমে আসা যা কিছু আছে তা সংরক্ষণ করার জন্য আপনার পর্যাপ্ত পরিমাণের স্মৃতি থাকা দরকার, এমনকি যদি আপনার জেএসএনে শেষ 20 টিবি সাড়া শেষের পরে থাকে }
ডাস্টিন

@ ডাস্টিন আপনি এটি io.LimitReaderপ্রতিরোধ করতে ব্যবহার করতে পারেন ।
ইনঙ্ক গুমাস

উত্তর:


239

এটি আপনার ইনপুটটি কী তা নির্ভর করে। আপনি যদি Decodeপদ্ধতিটির বাস্তবায়নের দিকে নজর দেন তবে json.Decoderএটি কোনও গো মানতে আনমশালিংয়ের আগে মেমরির পুরো JSON মানটিকে বাফার করে। সুতরাং বেশিরভাগ ক্ষেত্রে এটি আর কোনও স্মৃতি দক্ষ হবে না (যদিও এটি ভাষার ভবিষ্যতের সংস্করণে সহজেই পরিবর্তিত হতে পারে)।

সুতরাং থাম্বের আরও ভাল নিয়ম এটি:

  • ব্যবহারের json.Decoderআপনার ডেটা একটি থেকে আসছে যদি io.Readerস্ট্রিম, অথবা আপনি তথ্য একটি স্ট্রীম থেকে একাধিক মান ডিকোড করতে হবে।
  • আপনার json.Unmarshalযদি ইতিমধ্যে মেমরিতে JSON ডেটা থাকে তবে ব্যবহার করুন ।

এইচটিটিপি অনুরোধটি পড়ার ক্ষেত্রে, আমি json.Decoderযেহেতু আপনি অবশ্যই একটি স্ট্রিম থেকে স্পষ্টতই পড়ছেন তা আমি বেছে নেব।


25
এছাড়াও: গো 1.3 উত্স কোডটি পরিদর্শন করে, আমরা এও শিখতে পারি যে এনকোডিংয়ের জন্য, আপনি যদি কোন জসন.এনকোডার ব্যবহার করেন তবে এটি একটি গ্লোবাল বাফার পুল পুনরায় ব্যবহার করবে (নতুন সিঙ্ক.পুলের সাহায্যে), যা বাফার মন্থনকে অনেক হ্রাস করতে হবে যদি আপনি প্রচুর জসনকে এনকোড করে থাকেন। এখানে একমাত্র বৈশ্বিক পুল রয়েছে যাতে আলাদা আলাদা জসন রয়েছে nc এনকোডার এটিকে ভাগ করে। Json. মার্শাল ইন্টারফেসের জন্য এটি করা যায় না তার কারণ হ'ল বাইটগুলি ব্যবহারকারীকে ফিরিয়ে দেওয়া হয় এবং ব্যবহারকারীর কাছে পুলটিতে বাইটগুলি "ফেরত" দেওয়ার উপায় নেই। সুতরাং আপনি যদি অনেকগুলি এনকোডিং করে থাকেন তবে json. মার্শালের সর্বদা বেশ কিছুটা বাফার মন্থ থাকে।
আকতাউ

@ ফ্লিমজি: ​​আপনি কি নিশ্চিত? উত্স কোডটি এখনও বলে যে এটি ডিকোডিংয়ের আগে পুরো মানটি বাফারে পড়ে reads github.com/golang/go/blob/master/src/encoding/json/…Bufferedপদ্ধতি যদি আপনি কোন অতিরিক্ত তথ্য যে মান পর অভ্যন্তরীণ বাফার মধ্যে পাঠ করা হয় দেখা যাক নেই।
জেমস হেনস্ট্রিজ

@ জামেসহেনস্ট্রিজ: না, আপনি সম্ভবত ঠিক বলেছেন। আমি আপনার বক্তব্যটি আপনার ইচ্ছা থেকে আলাদাভাবে ব্যাখ্যা করছি ting বিভ্রান্তির জন্য দুঃখিত।
ঝাঁকুনি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.