Json.net क्रमबद्ध / deserialize व्युत्पन्न प्रकार?


98

json.net (newtonsoft)
मैं प्रलेखन के माध्यम से देख रहा हूं, लेकिन मुझे इस पर या इसके लिए सबसे अच्छा तरीका कुछ भी नहीं मिल रहा है।

public class Base
{
    public string Name;
}
public class Derived : Base
{
    public string Something;
}

JsonConvert.Deserialize<List<Base>>(text);

अब मेरे पास अनुक्रमित सूची में व्युत्पन्न वस्तुएं हैं। मैं सूची को कैसे मिटा सकता हूं और व्युत्पन्न प्रकारों को वापस पा सकता हूं?


इस प्रकार से वंशानुक्रम काम नहीं करता है। आप JsonConvert.Deserialize <Derived> (text) निर्दिष्ट कर सकते हैं; नाम फ़ील्ड शामिल करने के लिए। चूंकि डिराइव्ड IS ए बेस है (अन्य तरीके से नहीं), बेस को डिराइव्ड की परिभाषा के बारे में कुछ भी नहीं पता है।
एम। बैबॉक

क्षमा करें, थोड़ा स्पष्ट किया। मुद्दा यह है कि मेरे पास एक सूची है जिसमें आधार और व्युत्पन्न दोनों वस्तुएं हैं। इसलिए मुझे यह पता लगाने की आवश्यकता है कि मैं न्यूटॉन्सॉफ्ट को कैसे बताऊं कि कैसे व्युत्पन्न वस्तुओं को अलग करना है।
होगा

मैंने इसे हल किया। मेरे पास एक ही समस्या है
लुइस कार्लोस चवरिया

जवाबों:


46

यदि आप अपने में टाइप कर रहे हैं text(जैसा कि आपको इस परिदृश्य में होना चाहिए), तो आप इसका उपयोग कर सकते हैं JsonSerializerSettings

देखें: Newtonsoft JSON.NET के साथ IEnumerable <BaseType> में JSON को कैसे निष्क्रिय किया जाए

हालांकि सावधान रहें। सुरक्षा भेद्यता केTypeNameHandling = TypeNameHandling.None लिए अपने आप को खोलने के अलावा और कुछ का उपयोग करना ।


24
आप यह भी उपयोग कर सकते हैं TypeNameHandling = TypeNameHandling.Auto- यह $typeकेवल उदाहरणों के लिए एक संपत्ति जोड़ देगा जहां घोषित प्रकार (यानी Base) उदाहरण के प्रकार (यानी Derived) से मेल नहीं खाता है । इस तरह, यह आपके JSON को उतना फूला नहीं करता है जितना कि TypeNameHandling.All
एजे रिचर्डसन

मुझे JSON '..., ...' में निर्दिष्ट त्रुटि समाधान प्राप्त होता रहता है। पथ '$ प्रकार', पंक्ति 1, स्थिति 82. कोई विचार?
रिश्वत

3
सार्वजनिक समापन बिंदु पर इसका उपयोग करते समय सावधान रहें क्योंकि यह सुरक्षा मुद्दों को खोलता है: alphabot.com/security/blog/2017/net/…
gjvdkamp

1
@gjvdkamp JEEZ इसके लिए धन्यवाद, मुझे इस बारे में पता नहीं था। मेरी पोस्ट में जोड़ देंगे।
कामरानिकस

96

आपको टाइप नाम हैंडलिंग को सक्षम करना होगा और सेटिंग्स पैरामीटर के रूप में (डी) सीरियल को पास करना होगा।

Base object1 = new Base() { Name = "Object1" };
Derived object2 = new Derived() { Something = "Some other thing" };
List<Base> inheritanceList = new List<Base>() { object1, object2 };

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
string Serialized = JsonConvert.SerializeObject(inheritanceList, settings);
List<Base> deserializedList = JsonConvert.DeserializeObject<List<Base>>(Serialized, settings);

इसके परिणामस्वरूप व्युत्पन्न वर्गों का सही deserialization होगा। इसका एक दोष यह है कि यह आपके द्वारा उपयोग की जा रही सभी वस्तुओं को नाम देगा, जैसे कि यह उस सूची का नाम देगा जिसमें आप वस्तुओं को डाल रहे हैं।


31
+1। जब तक मुझे वास्तव में पता चला कि आपको SerializeObject और DeserializeObject के लिए एक ही सेटिंग्स का उपयोग करने की आवश्यकता है, तब तक मैं 30 मिनट के लिए जा रहा था। मुझे लगता है कि अगर यह deserializing है, तो मुझे मूर्खतापूर्ण रूप से $ प्रकार का उपयोग करेगा।
एरती-क्रिस इल्मा

24
TypeNameHandling.Autoयह भी करेगा, और यह अच्छा है क्योंकि यह उदाहरण प्रकार नाम नहीं लिखता है जब यह फ़ील्ड / संपत्ति के प्रकार से मेल खाता है, जो अक्सर अधिकांश फ़ील्ड / गुणों के मामले में होता है।
रोमन स्टार्कोव

2
यह तब काम नहीं करता है जब किसी अन्य समाधान / परियोजना पर डिसरिज़लाइज़ेशन किया जाता है। क्रमांकन पर समाधान का नाम इस प्रकार है: "SOLUTIONNAME.Models.Model"। दूसरे समाधान पर डिसेररलाइजेशन पर यह "JsonSerializationException फेंक देगा: असेंबली 'SOLNNAME' को लोड नहीं कर सका।
दुख की बात है CRUD डेवलपर

19

चूंकि प्रश्न इतना लोकप्रिय है, इसलिए यह जोड़ना उपयोगी हो सकता है कि यदि आप संपत्ति के प्रकार और उसके मूल्य को नियंत्रित करना चाहते हैं तो क्या करें।

कस्टम JsonConverterप्रॉपर्टी को मैन्युअल रूप से जाँचने और सेट करने के लिए कस्टम एस को हैंडल (डी) सीरियलाइजेशन लिखने का लंबा तरीका है ।

एक सरल तरीका JsonSubTypes का उपयोग करना है , जो विशेषताओं के माध्यम से सभी बॉयलरप्लेट को संभालता है:

[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
    public virtual string Sound { get; }
    public string Color { get; set; }
}

public class Dog : Animal
{
    public override string Sound { get; } = "Bark";
    public string Breed { get; set; }
}

public class Cat : Animal
{
    public override string Sound { get; } = "Meow";
    public bool Declawed { get; set; }
}

3
मुझे जरूरत है, लेकिन मैं बेस क्लास को सभी "नाउनसुबटाइप" के बारे में अवगत कराने का प्रशंसक नहीं हूँ ...
मैट नोल्स

2
यदि आप दस्तावेज़ को देखते हैं तो अन्य विकल्प भी हैं। मैंने केवल उदाहरण दिया जो मुझे अधिक पसंद है।
rzippo

1
यह सुरक्षित दृष्टिकोण है जो आपकी सेवा को डी-सीरीज़ेशन पर मनमाने ढंग से लोड करने के लिए उजागर नहीं करता है।
डेविड बर्ग

3

इस JsonKnownTypes का उपयोग करें, यह उपयोग करने के लिए बहुत समान है, यह सिर्फ json में भेदभाव करनेवाला जोड़ देता है:

[JsonConverter(typeof(JsonKnownTypeConverter<BaseClass>))]
[JsonKnownType(typeof(Base), "base")]
[JsonKnownType(typeof(Derived), "derived")]
public class Base
{
    public string Name;
}
public class Derived : Base
{
    public string Something;
}

अब जब आप को क्रमानुसार json में वस्तु को जोड़ने की जाएगी "$type"साथ "base"और "derived"मूल्य और यह deserialize के लिए उपयोग किया जाएगा

क्रमबद्ध सूची उदाहरण:

[
    {"Name":"some name", "$type":"base"},
    {"Name":"some name", "Something":"something", "$type":"derived"}
]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.