2012-08-01 10 views
51

मैं ASP.NET MVC वेब एपीआई का उपभोग करने के लिए कुछ कोड स्थानांतरित करने के लिए कोशिश कर रहा हूँ JSON डेटा के बजाय सोप Xml उत्पन्न।NewtonSoft.Json को क्रमानुसार और deserialize प्रकार की संपत्ति IEnumerable साथ वर्ग <ISomeInterface>

मैं serializing और deserializing प्रकार के गुणों के साथ किसी समस्या का सामना किया है:

:

public interface ISample{ 
    int SampleId { get; set; } 
} 
public class Sample : ISample{ 
    public int SampleId { get; set; } 
} 
public class SampleGroup{ 
    public int GroupId { get; set; } 
    public IEnumerable<ISample> Samples { get; set; } 
} 
} 

मैं के साथ आसानी से SampleGroup के उदाहरण को क्रमानुसार कर सकते हैं:

IEnumerable<ISomeInterface>. 

यहाँ एक सरल उदाहरण है

var sz = JsonConvert.SerializeObject(sampleGroupInstance); 

हालांकि इसी deserialize विफल रहता है:

JsonConvert.DeserializeObject<SampleGroup>(sz); 
इस अपवाद संदेश के साथ

:

"प्रकार JsonSerializationExample.ISample का एक उदाहरण नहीं बना सका। प्रकार एक इंटरफ़ेस या अमूर्त वर्ग है और instantated नहीं किया जा सकता "

मैं निकाले जाते हैं, तो एक JsonConverter मैं अपनी संपत्ति के रूप में निम्नानुसार को सजाने कर सकते हैं:।

[JsonConverter(typeof (SamplesJsonConverter))] 
public IEnumerable<ISample> Samples { get; set; } 

यहाँ है JsonConverter:

public class SamplesJsonConverter : JsonConverter{ 
    public override bool CanConvert(Type objectType){ 
    return (objectType == typeof (IEnumerable<ISample>)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer){ 
    var jA = JArray.Load(reader); 
    return jA.Select(jl => serializer.Deserialize<Sample>(new JTokenReader(jl))).Cast<ISample>().ToList(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){ 
    ... What works here? 
    } 
} 

यह कनवर्टर अक्रमांकन समस्या का हल है, लेकिन मैं फिर से काम कर पाने के लिए क्रमबद्धता WriteJson विधि कोड करने के लिए कैसे समझ नहीं सकता।

किसी की सहायता कर सकते हैं?

यह एक "सही" जिस तरह से पहली जगह में समस्या को हल करने है?

+0

नीचे दिए गए उत्तरों के अतिरिक्त, आप ['CanWrite'] (http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonConverter_CanWrite.htm) को ओवरराइड कर सकते हैं और 'false' वापस कर सकते हैं। देखें [एक कस्टम जेसन कनवर्टर में डिफ़ॉल्ट क्रमिकरण का उपयोग कैसे करें] (https://stackoverflow.com/questions/29616596/how-to-use-default-serialization-in-a-custom-jsonconverter/29616648#29616648)। – dbc

उत्तर

2

अपनी परियोजनाओं में, कोड के इस टुकड़े हमेशा एक डिफ़ॉल्ट serializer जो निर्धारित मूल्य को धारावाहिक के रूप में काम के रूप में अगर वहाँ कोई विशेष कनवर्टर था:

serializer.Serialize(writer, value); 
+2

सीरियलाइजेशन ठीक काम करता है। समस्या एक इंटरफेस के रूप में घोषित संपत्ति के लिए de-serializing है। कस्टमक्रिएशन कनवर्टर को कार्यान्वित करना और उसे JsonConvert.DeserializeObject को पास करना उत्तर लगता है। – AndyDBell

58

आप अपने मॉडल रखने के लिए, JsonConverterAttribute उपयोग करने के लिए की जरूरत नहीं है साफ है, यह भी CustomCreationConverter उपयोग करते हैं, कोड सरल है:

public class SampleConverter : CustomCreationConverter<ISample> 
{ 
    public override ISample Create(Type objectType) 
    { 
     return new Sample(); 
    } 
} 

तब:

var sz = JsonConvert.SerializeObject(sampleGroupInstance); 
JsonConvert.DeserializeObject<SampleGroup>(sz, new SampleConverter()); 

प्रलेखन: Deserialize with CustomCreationConverter

+1

धन्यवाद। यह अच्छी तरह से काम करता है। – AndyDBell

+1

धन्यवाद, आपने मेरा दिन बचाया। मेरा खुद का जेसन कनवर्टर काम नहीं कर रहा था मुझे नहीं पता कि क्यों। आपका समाधान एक आकर्षण की तरह काम करता है और बहुत आसान है –

1

मैं इस काम मिल गया:

स्पष्ट रूपांतरण

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
            JsonSerializer serializer) 
    { 
     var jsonObj = serializer.Deserialize<List<SomeObject>>(reader); 
     var conversion = jsonObj.ConvertAll((x) => x as ISomeObject); 

     return conversion; 
    } 
4

महान समाधान, धन्यवाद! मैं AndyDBell के सवाल और चुओंग Le के जवाब में ले लिया दो विभिन्न इंटरफेस के कार्यान्वयन के साथ एक उदाहरण के निर्माण के लिए:

public interface ISample 
{ 
    int SampleId { get; set; } 
} 

public class Sample1 : ISample 
{ 
    public int SampleId { get; set; } 
    public Sample1() { } 
} 


public class Sample2 : ISample 
{ 
    public int SampleId { get; set; } 
    public String SampleName { get; set; } 
    public Sample2() { } 
} 

public class SampleGroup 
{ 
    public int GroupId { get; set; } 
    public IEnumerable<ISample> Samples { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     //Sample1 instance 
     var sz = "{\"GroupId\":1,\"Samples\":[{\"SampleId\":1},{\"SampleId\":2}]}"; 
     var j = JsonConvert.DeserializeObject<SampleGroup>(sz, new SampleConverter<Sample1>()); 
     foreach (var item in j.Samples) 
     { 
      Console.WriteLine("id:{0}", item.SampleId); 
     } 
     //Sample2 instance 
     var sz2 = "{\"GroupId\":1,\"Samples\":[{\"SampleId\":1, \"SampleName\":\"Test1\"},{\"SampleId\":2, \"SampleName\":\"Test2\"}]}"; 
     var j2 = JsonConvert.DeserializeObject<SampleGroup>(sz2, new SampleConverter<Sample2>()); 
     //Print to show that the unboxing to Sample2 preserved the SampleName's values 
     foreach (var item in j2.Samples) 
     { 
      Console.WriteLine("id:{0} name:{1}", item.SampleId, (item as Sample2).SampleName); 
     } 
     Console.ReadKey(); 
    } 
} 

और SampleConverter करने के लिए एक जेनेरिक वर्जन:

public class SampleConverter<T> : CustomCreationConverter<ISample> where T: new() 
{ 
    public override ISample Create(Type objectType) 
    { 
     return ((ISample)new T()); 
    } 
} 
15

यह काफी सरल और से बाहर है json.net द्वारा दिए गए बॉक्स समर्थन, तो आप सिर्फ और serializing करते समय निम्न JsonSettings उपयोग करने के लिए deserializing:

JsonConvert.SerializeObject(graph,Formatting.None, new JsonSerializerSettings() 
{ 
    TypeNameHandling =TypeNameHandling.Objects, 
    TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple 
}); 

और डी के लिए नीचे दिए गए कोड का उपयोग serialzing: वस्तु

JsonConvert.DeserializeObject(Encoding.UTF8.GetString(bData),type, 
    new JsonSerializerSettings(){TypeNameHandling = TypeNameHandling.Objects} 
); 

बस JsonSerializerSettings लिख लेना चाहिए प्रारंभकर्ता, कि आप के लिए महत्वपूर्ण है।

0

होने कि:

public interface ITerm 
{ 
    string Name { get; } 
} 

public class Value : ITerm... 

public class Variable : ITerm... 

public class Query 
{ 
    public IList<ITerm> Terms { get; } 
... 
} 

मैं रूपांतरण चाल में कामयाब रहे कि लागू करने:

string JsonQuery = "{\"Terms\":[{\"Value\":\"This is \"},{\"Variable\":\"X\"},{\"Value\":\"!\"}]}"; 
... 
var query = new Query(new Value("This is "), new Variable("X"), new Value("!")); 
var serializeObject = JsonConvert.SerializeObject(query, new TermConverter()); 
Assert.AreEqual(JsonQuery, serializeObject); 
... 
var queryDeserialized = JsonConvert.DeserializeObject<Query>(JsonQuery, new TermConverter()); 
7

मुझे लगता है कि समस्या का समाधान:

public class TermConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var field = value.GetType().Name; 
     writer.WriteStartObject(); 
     writer.WritePropertyName(field); 
     writer.WriteValue((value as ITerm)?.Name); 
     writer.WriteEndObject(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
     JsonSerializer serializer) 
    { 
     var jsonObject = JObject.Load(reader); 
     var properties = jsonObject.Properties().ToList(); 
     var value = (string) properties[0].Value; 
     return properties[0].Name.Equals("Value") ? (ITerm) new Value(value) : new Variable(value); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof (ITerm) == objectType || typeof (Value) == objectType || typeof (Variable) == objectType; 
    } 
} 

यह मेरे को क्रमानुसार और तरह JSON में deserialize करने की अनुमति देता के लिए एक विशेष सेटिंग का उपयोग करके JsonSerializerSettings जो TypeNameHandling.All

TypeNameHandling सेटिंग कहा जाता है शामिल JSON serializing जब टाइप जानकारी और प्रकार की जानकारी को पढ़ने के लिए इतना है कि बनाने के प्रकार जब deserializing JSON

क्रमबद्धता बनाई गई हैं:

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 
var text = JsonConvert.SerializeObject(configuration, settings); 

Deserialization:

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 
var configuration = JsonConvert.DeserializeObject<YourClass>(json, settings); 

वर्ग YourClass आधार प्रकार क्षेत्रों के किसी भी प्रकार हो सकता है और यह ठीक से धारावाहिक रूप दिया जाएगा।

संबंधित मुद्दे