কীভাবে গো দিয়ে জেএসএন-তে কোনও ফাঁকা কাঠামো মার্শাল করবেন না?


91

আমার এইরকম স্ট্রাক্ট রয়েছে:

type Result struct {
    Data       MyStruct  `json:"data,omitempty"`
    Status     string    `json:"status,omitempty"`
    Reason     string    `json:"reason,omitempty"`
}

তবে মাইস্ট্রাস্টের উদাহরণটি পুরোপুরি খালি থাকলেও (অর্থাত, সমস্ত মানগুলি ডিফল্ট হয়), এটি সিরিয়ালীকৃত হচ্ছে:

"data":{}

আমি জানি যে এনকোডিং / জসন ডক্সটি "খালি" ক্ষেত্রগুলি নির্দিষ্ট করে:

মিথ্যা, 0, কোনও শূন্য পয়েন্টার বা ইন্টারফেস মান এবং কোনও অ্যারে, স্লাইস, মানচিত্র বা দৈর্ঘ্যের শূন্য

তবে সমস্ত খালি / ডিফল্ট মান সহ কোনও কাঠামোর জন্য কোনও বিবেচনা নেই। এর সমস্ত ক্ষেত্রও ট্যাগযুক্ত omitempty, তবে এর কোনও প্রভাব নেই।

আমি কীভাবে JSON প্যাকেজটি খালি স্ট্রাক্টের ক্ষেত্রটি মার্শাল না করতে পারি ?

উত্তর:


142

দস্তাবেজগুলি যেমন বলে, "যে কোনও শূন্য পয়েন্টার।" - কাঠামোটিকে একটি পয়েন্টার তৈরি করুন। পয়েন্টারগুলির স্পষ্ট "খালি" মান রয়েছে:nil

স্থির করুন - স্ট্রাক পয়েন্টার ক্ষেত্রের সাথে প্রকারটি নির্ধারণ করুন :

type Result struct {
    Data       *MyStruct `json:"data,omitempty"`
    Status     string    `json:"status,omitempty"`
    Reason     string    `json:"reason,omitempty"`
}

এর পরে একটি মান:

result := Result{}

মার্শাল যেমন হবে:

{}

ব্যাখ্যা: লক্ষ্য করুন *MyStruct আমাদের ধরণের সংজ্ঞাটি । জেএসএন সিরিয়ালাইজেশন এটি পয়েন্টার কিনা তা বিবেচনা করে না - এটি রানটাইম বিশদ। সুতরাং স্ট্রাক্ট ফিল্ডগুলিকে পয়েন্টারগুলিতে তৈরি করার ক্ষেত্রে কেবল সংকলন এবং রানটাইম অন্তর্ভুক্ত থাকবে)।

শুধু মনে রাখবেন যদি আপনার কাছ থেকে ক্ষেত্র প্রকার পরিবর্তন না MyStructকরার জন্য *MyStruct, আপনি এটি পূরণ করতে, তাই মত struct হয় মান পয়েন্টার করতে হবে:

Data: &MyStruct{ /* values */ }

4
ম্যাটকে আশীর্বাদ করুন, এটিই আমি খুঁজছিলাম
ভেঙ্কটা এসএসকেএম চৈতন্য

@ ম্যাট, আপনি কি নিশ্চিত যে &MyStruct{ /* values */ }নিল পয়েন্টার হিসাবে গণনা করা যায়? মান শূন্য হয় না।
শুজেং

@ ম্যাট এই ডিফল্ট আচরণ করা সম্ভব? আমি সর্বদা বাদ দিতে চাই। (মূলত সমস্ত স্ট্রাক্টের প্রতিটি ক্ষেত্রেই ট্যাগটি ব্যবহার করবেন না)
মোহিত সিং

18

@ চাচারিত যেমন একটি মন্তব্যে উল্লেখ করেছেন, আপনি json.Marshalerএটি MyStructপ্রয়োগ করে প্রতিটি স্ট্রাক্টে একটি কাস্টম জেএসওএন মার্শালিং ফাংশন প্রয়োগ করে আরও কাজ করতে পারেন can এটি অতিরিক্ত ব্যবহারের পক্ষে মূল্যবান কিনা বা আপনি আপনার JSON এ খালি স্ট্রাক্ট নিয়ে বেঁচে থাকার জন্য প্রস্তুত কিনা তা সত্যই আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে তবে আমি যে প্যাটার্নটি ব্যবহার করি তা এখানে প্রয়োগ করা হয়েছে Result:

type Result struct {
    Data       MyStruct
    Status     string   
    Reason     string    
}

func (r Result) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        Data     *MyStruct   `json:"data,omitempty"`
        Status   string      `json:"status,omitempty"`
        Reason   string      `json:"reason,omitempty"`
    }{
        Data:   &r.Data,
        Status: r.Status,
        Reason: r.Reason,
    })        
}

func (r *Result) UnmarshalJSON(b []byte) error {
    decoded := new(struct {
        Data     *MyStruct   `json:"data,omitempty"`
        Status   string      `json:"status,omitempty"`
        Reason   string      `json:"reason,omitempty"`
    })
    err := json.Unmarshal(b, decoded)
    if err == nil {
        r.Data = decoded.Data
        r.Status = decoded.Status
        r.Reason = decoded.Reason
    }
    return err
}

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

এছাড়াও, আপনাকে ইনলাইন স্ট্রাইক ব্যবহার করতে হবে না, আপনি নামযুক্ত তৈরি করতে পারেন। আমি কোড সমাপ্তির সাথে লাইটইড ব্যবহার করি, তাই বিশৃঙ্খলা এড়াতে আমি ইনলাইন পছন্দ করি।


9

Data এটি একটি প্রাথমিক কাঠামো, সুতরাং এটি খালি বিবেচনা করা হয় না কারণ encoding/json কেবল তাত্ক্ষণিক মানটি দেখায়, কাঠামোর ভিতরে ক্ষেত্রগুলি নয়।

দুর্ভাগ্যক্রমে বর্তমানে nilথেকে ফিরে আসা json.Marhslerকাজ করে না:

func (_ MyStruct) MarshalJSON() ([]byte, error) {
    if empty {
        return nil, nil // unexpected end of JSON input
    }
    // ...
}

আপনি দিতে পারে Result একটি মার্শেলারও , তবে এটি চেষ্টা করার মতো নয়।

ম্যাট পরামর্শ হিসাবে একমাত্র বিকল্প হ'ল Dataপয়েন্টার তৈরি করা এবং মানটি সেট করা nil


4
আমি দেখতে পাচ্ছি না কেন স্ট্রাক্টের শিশু ক্ষেত্রগুলি পরীক্ষা encoding/json করতে পারে না । এটি খুব দক্ষ হবে না, হ্যাঁ। তবে এটি অবশ্যই অসম্ভব নয়।
নিমো

@ নেমো আমি আপনার বক্তব্যটি দেখতে পাচ্ছি, আমি শব্দটির পরিবর্তন করেছি। এটি এটি করে না কারণ এটি দক্ষ হবে না। এটা দিয়ে কাজ করা যেতে পারে json.Marshalerএকটি কেস বাই কেস ভিত্তিতে যদিও উপর।
লুক

4
এটা না করা সম্ভব না খাসি সিদ্ধান্ত নেন বা MyStructখালি একটি প্রয়োগ করে json.Marshalerউপর MyStructনিজেই। প্রুফ: play.golang.org/p/UEC8A3JGvx
চકૃત

এটি করতে আপনাকে নিজের ধারণক্ষমতার json.Marshalerউপর প্রয়োগ Resultকরতে হবে যা খুব অসুবিধে হতে পারে।
চকৃত

4

এই বৈশিষ্ট্যটির জন্য একটি অসামান্য গোলং প্রস্তাব রয়েছে যা 4 বছরেরও বেশি সময় ধরে সক্রিয় ছিল, সুতরাং এই মুহুর্তে, এটি ধারণা করা নিরাপদ যে এটি শীঘ্রই যে কোনও সময় এটি স্ট্যান্ডার্ড লাইব্রেরিতে পরিণত করবে না। @ ম্যাট যেমন উল্লেখ করেছেন, traditional তিহ্যবাহী পদ্ধতি হ'ল স্ট্রাক্টগুলিকে রূপান্তর করা থেকে পয়েন্টার টু structs মধ্যে । যদি এই পদ্ধতিটি অক্ষম (বা অবৈধ) হয়, তবে একটি বিকল্প হ'ল বিকল্প জেসন এনকোডার ব্যবহার করা যা শূন্য মানের স্ট্রোকগুলি বাদ দেওয়া সমর্থন করে ।

আমি যখন ট্যাগ প্রয়োগ করা হয় তখন শূন্য মানের স্ট্রাক্ট বাদ দেওয়ার জন্য যুক্ত সমর্থন সহ গোলং জেসন লাইব্রেরির ( কেরার্কেম / জেসন ) একটি আয়না তৈরি করেছি । এই গ্রন্থাগার ডিটেক্ট করে zeroness জনপ্রিয় YAML এনকোডার একটি অনুরূপ পদ্ধতিতে -যেতে যেতে yaml দ্বারা যাও recursively চেক প্রকাশ্য struct হয় ক্ষেত্রেরomitempty

যেমন

$ go get -u "github.com/clarketm/json"
import (
    "fmt"
    "github.com/clarketm/json" // drop-in replacement for `encoding/json`
)

type Result struct {
    Data   MyStruct `json:"data,omitempty"`
    Status string   `json:"status,omitempty"`
    Reason string   `json:"reason,omitempty"`
}

j, _ := json.Marshal(&Result{
    Status: "204",
    Reason: "No Content",
})

fmt.Println(string(j))
// Note: `data` is omitted from the resultant json.
{
  "status": "204"
  "reason": "No Content"
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.