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?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With