I need to deserialize jsons to a type that contains a property of interface type - IExceptionModel. I prescribe maps for interfaces to classes like this:
public static class JsonSerialization
{
public static T FromJson<T>(this string obj) => JsonConvert.DeserializeObject<T>(obj, Settings);
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
ContractResolver = new ContractResolver()
};
private class ContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
var result = base.CreateContract(objectType);
if (objectType == typeof(IExceptionModel))
{
result.CreatedType = typeof(Status);
result.DefaultCreator = () => result.CreatedType.GetConstructor(new Type[0]).Invoke(null);
}
return result;
}
}
}
Here are my interface and class types:
public interface IExceptionModel : IModelBase
{
public string Message { get; set; }
public byte Index { get; set; }
}
public class ExceptionModel : IExceptionModel
{
public string Message { get ; set ; }
public byte Index { get; set; }
}
Here is the class to deserialize to:
public class Status
{
public IExceptionModel Error { get; set; }
}
When I take a proper input string like:
{
"Error" : {
"Message": "Error",
"Index": 404
}
}
and feed it to FromJson<Status> method, described above, I get Error property set to null, although I believe I have resolved the contract for the interface. What else do I need to do in order to make it work?
CodePudding user response:
I made some corrections and this worked for me:
result.CreatedType = typeof(Status);
--> result.CreatedType = typeof(ExceptionModel);
public byte Index { get; set; }
--> public int Index { get; set; }
I uploaded this online example: https://dotnetfiddle.net/ETSJee
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public interface IModelBase {}
public interface IExceptionModel : IModelBase
{
public string Message { get; set; }
public int Index { get; set; }
}
public class ExceptionModel : IExceptionModel
{
public string Message { get ; set ; }
public int Index { get; set; }
}
public class Status
{
public IExceptionModel Error { get; set; }
}
public static class JsonSerialization
{
public static T FromJson<T>(this string obj)
{
return JsonConvert.DeserializeObject<T>(obj, Settings);
}
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
ContractResolver = new ContractResolver()
};
private class ContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
var result = base.CreateContract(objectType);
if (objectType == typeof(IExceptionModel))
{
result.CreatedType = typeof(ExceptionModel);
result.DefaultCreator = () => result.CreatedType.GetConstructor(new Type[0]).Invoke(null);
}
return result;
}
}
}
class Program
{
static void Main(string[] args)
{
var txt = @"
{
'Error' : {
'Message': 'Error',
'Index': 404
}
}
";
var obj = JsonSerialization.FromJson<Status>(txt);
Console.WriteLine(obj.Error.Index);
Console.WriteLine(obj.Error.Message);
}
}
CodePudding user response:
this works for me without any contract resolvers
var status = JsonConvert.DeserializeObject<Status>(txt);
public class Status
{
public IExceptionModel Error { get; set; }
[JsonConstructor]
public Status (ExceptionModel error) {
Error=error;
}
public Status() {}
}