Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NewtonSoft.Json Serialize and Deserialize class with property of type IEnumerable<ISomeInterface>

I am trying to move some code to consume ASP.NET MVC Web API generated Json data instead of SOAP Xml.

I have run into a problem with serializing and deserializing properties of type:

IEnumerable<ISomeInterface>. 

Here is a simple example:

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; }  } } 

I can serialize instances of SampleGroup easily with:

var sz = JsonConvert.SerializeObject( sampleGroupInstance ); 

However the corresponding deserialize fails:

JsonConvert.DeserializeObject<SampleGroup>( sz ); 

with this exception message:

"Could not create an instance of type JsonSerializationExample.ISample. Type is an interface or abstract class and cannot be instantated."

If I derive a JsonConverter I can decorate my property as follows:

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

Here is the 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?   } } 

This converter solves the deserialization problem but I cannot figure how to code the WriteJson method to get serialization working again.

Can anybody assist?

Is this a "correct" way to solve the problem in the first place?

like image 763
AndyDBell Avatar asked Aug 01 '12 07:08

AndyDBell


2 Answers

You don't need to use JsonConverterAttribute, just keep your model clean and use CustomCreationConverter instead, the code is simpler:

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

Then:

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

Documentation: Deserialize with CustomCreationConverter

like image 120
cuongle Avatar answered Sep 22 '22 04:09

cuongle


It is quite simple and out of the box support provided by json.net, you just have to use the following JsonSettings while serializing and Deserializing:

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

and for Deserialzing use the below code:

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

Just take a note of the JsonSerializerSettings object initializer, that is important for you.

like image 32
Sunil S Avatar answered Sep 26 '22 04:09

Sunil S