मैं JSON.net का उपयोग करके कक्षाओं को क्रमबद्ध कर रहा हूं और "$type" एनोटेशन डालने के लिए TypeNameHandling=Auto का उपयोग कर रहा हूं। उदाहरण के लिए, मान लें कि यह मेरी कक्षा है:

[JsonObject]
public class MyClass
{
    [JsonProperty]
    public ISomeInterfaceA MyA { get; set; }

    [JsonProperty]
    public ISomeInterfaceB MyB { get; set; }
}

इसके साथ, "MyA" और "MyB" दोनों को "$type" विशेषता प्राप्त होती है। दुर्भाग्य से, मैं एक अजीब स्थिति में हूं जहां मुझे "$ प्रकार" रखने के लिए "MyA" की आवश्यकता है, लेकिन "MyB" में "$type" नहीं होना चाहिए। क्या json.net में कुछ भी है जो मुझे TypeNameHandling.Auto के व्यवहार को अनुकूलित करने की अनुमति देगा ताकि मैं मैन्युअल रूप से चुन सकूं कि मुझे यह कहां चाहिए या नहीं?

मैं ऐसा क्यों करना चाहता हूं, जटिल कारण यह है कि मैं एक अन्य विरासत धारावाहिक से JSON.net पर माइग्रेट कर रहा हूं, और मैं बड़े को फिर से लिखने से बचने के लिए पुराने और नए धारावाहिक के बीच के अंतर को कम करने का प्रयास कर रहा हूं। JSON का उपभोग करने वाले जावास्क्रिप्ट कोड की मात्रा।

0
mmgagnondi 3 फरवरी 2021, 00:14

1 उत्तर

सबसे बढ़िया उत्तर

आप इसे एक कस्टम कनवर्टर का उपयोग करके प्राप्त कर सकते हैं।

कहो यह आपकी कक्षा है:

[JsonObject]
public class MyClass {
    [JsonProperty]
    public ISomeInterfaceA MyA { get; set; }
    
    [JsonProperty]
    [JsonConverter(typeof(NoTypeConverter))]
    public ISomeInterfaceA MyB { get; set; }
}

हमें एक कस्टम कनवर्टर चाहिए:

public class NoTypeConverter: JsonConverter<ISomeInterfaceA> {
    public override ISomeInterfaceA ReadJson(JsonReader reader, Type objectType, ISomeInterfaceA existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, ISomeInterfaceA value, JsonSerializer serializer)
    {
       // Note: this is not the most efficient way to do this, but you can customise this how you see fit.
        writer.WriteRawValue(JsonConvert.SerializeObject(value));
    }

    public override bool CanWrite => true;

    public override bool CanRead => false;
}

फिर:

var stuff = JsonConvert.SerializeObject(new MyClass 
{ MyA = new A { Banana = "cheese" }, 
  MyB = new A { Banana = "notype"} },
new JsonSerializerSettings{ TypeNameHandling=TypeNameHandling.Auto });
                                                        
Console.WriteLine(stuff); // {"MyA":{"$type":"whatever, here","Banana":"cheese"},"MyB":{"Banana":"notype"}}

ध्यान दें, हालांकि, आप इस तरह से अपने प्रकार पर वापस नहीं जा सकते क्योंकि MyB के लिए प्रकार की जानकारी अनुपलब्ध है

var x = JsonConvert.DeserializeObject<MyClass>(stuff, 
    new JsonSerializerSettings{ TypeNameHandling=TypeNameHandling.Auto });

वह फेंक देगा

अनियंत्रित अपवाद। Newtonsoft.Json.JsonSerializationException: ISomeInterfaceA प्रकार का एक उदाहरण नहीं बना सका। प्रकार एक इंटरफ़ेस या अमूर्त वर्ग है और इसे तत्काल नहीं किया जा सकता है। पथ 'MyB.Banana', पंक्ति 1, स्थिति 69।

0
zaitsman 3 फरवरी 2021, 00:57
धन्यवाद, मैं उस संभावना से अवगत था, लेकिन उम्मीद कर रहा था कि मुझे इसका सहारा नहीं लेना पड़ेगा क्योंकि एक नकारात्मक पहलू है: आपका समाधान पुनरावर्ती है और सभी बच्चों और उप-बच्चों को प्रभावित करेगा, जबकि मैं उपस्थिति या अनुपस्थिति को लक्षित करने की उम्मीद कर रहा था उप-वस्तुओं को भी प्रभावित किए बिना एक विशिष्ट स्तर पर "$ प्रकार" का
 – 
mmgagnondi
3 फरवरी 2021, 01:00
1
अंत में मैंने इस पर एक भिन्नता का उपयोग किया। टाइपिंग जानकारी को छोड़ने के लिए कनवर्टर के बजाय, मैंने एक कनवर्टर बनाया जो उत्सर्जित जानकारी टाइप करता है, फिर प्रतिबिंब द्वारा कक्षा के सभी गुणों पर पुनरावृत्त करता है और इसके सदस्यों को एक-एक करके क्रमबद्ध करता है। इस तरह मेरा पूरा नियंत्रण है। उतना आसान नहीं जितना मुझे उम्मीद थी, लेकिन काम पूरा हो जाता है
 – 
mmgagnondi
3 फरवरी 2021, 17:20