我们在使用Newtonsoft.Json进行反序列化类中的接口属性的时候,Newtonsoft.Json会因找不到具体实现类,无法进行反序列化。
public class Student
{
public string Name { get; set; }
//这个是用来测试泛型是否能序列化和反序列化
public T age { get; set; }
public IClient Client { get; set; }
}
public interface IClient
{
string Name { get; set; }
void GetClient();
}
public class Client : IClient
{
public string Name { get; set; }
public void GetClient()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
//按照正常流程来进行序列化和反序列话
Student student = new Student()
{
Name = "123465",
age = 12,
Client = new Client()
{
Name = "哈哈"
}
};
//序列化成Json字符串
string json = JsonConvert.SerializeObject(student);
//将Json字符串反序列化成Student对象
Student result = JsonConvert.DeserializeObject>(json);
Console.WriteLine(result.Client.Name);
}
}
Could not create an instance of type Redis测试.IClient. Type is an interface or abstract class and cannot be instantiated. Path ‘Client.Name’
百度翻译:无法创建redis测试.iclient类型的实例。类型是接口或抽象类,无法实例化。路径“client.name“
我们在序列化完之后的Json是这样子的
{"Name":"123465","age":12,"Client":{"Name":"哈哈"}}
个人认为,在反序列化的时候,遇到IClient属性的时候,因为我们没有告诉序列化器该怎么序列化,然后序列化器只好按照自己反序列化对象流程走,但是它发现类型是一个接口,不能进行实例化,而它也不知道具体实现类是谁,所以就报出这个错误。
我是用的方式是告诉序列化器,遇到这个接口时该怎么反序列化,怎么告诉呢?这得用到JsonConverter这个抽象转换类
定义一个ClientJsonConverter类,继承JsonConverter
class ClientJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
//我们能转换任何东西
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
//显性指定要转换的实现类
return serializer.Deserialize(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//默认序列化流程
serializer.Serialize(writer, value);
}
}
然后在我们的Student类进行添加特性
[JsonConverter(typeof(ClientJsonConverter))]
public IClient Client { get; set; }
第二种方式也是自定义类继承JsonConverter来解决,不过,和第一种方式不同的是,它不用我们在student类里面添加特性。
自定义ClientJsonConverter2继承JsonConverter
class ClientJsonConverter2:JsonConverter
{
public override bool CanConvert(Type objectType)
{
//如果遇到了IClient,我们才进行转换
if (objectType.FullName == typeof(IClient).FullName)
{
return true;
}
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
//再判断一次,如果是IClient接口,那么我们指定具体实现类型
if (objectType.FullName == typeof(IClient).FullName)
{
return serializer.Deserialize(reader);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//按正常流程序列化
serializer.Serialize(writer, value);
}
}
Student类和最上面的一样
class Program
{
static void Main(string[] args)
{
Student student = new Student()
{
Name = "123465",
age = 12,
Client = new Client()
{
Name = "哈哈"
}
};
//序列化成Json
string json = JsonConvert.SerializeObject(student);
//使用另一个序列化器来进行反序列化
JsonSerializer serializer = new JsonSerializer();
//把我们自定义的JsonConverter放进序列化器(相当于告诉序列化器该怎么序列化)
serializer.Converters.Add(new ClientJsonConverter2());
//进行反序列化
JsonTextReader reader = new JsonTextReader(new StringReader(json));
Student result = serializer.Deserialize>(reader);
//输出结果
Console.WriteLine(result.Client.Name);
}
}
成功!
这两种解决方法适用的环境是什么呢?第一种解决方式适用于序列化自定义的类,而类中有接口属性,第二种解决方式适用于序列化无法进行修改的类(系统类,框架定义的类等等),这些类中也有接口属性
https://stackoverflow.com/questions/2254872/using-json-net-converters-to-deserialize-properties