我正在尝试移动一些代码来使用MVC Web API生成的Json数据而不是SOAP Xml ASP.NET。
我在序列化和反序列化类型的属性时遇到了问题:
IEnumerable<ISomeInterface>.
下面是一个简单的示例:
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; }
}
}
我可以使用以下方法轻松序列化样本组的实例:
var sz = JsonConvert.SerializeObject( sampleGroupInstance );
但是,相应的反序列化失败:
JsonConvert.DeserializeObject<SampleGroup>( sz );
包含以下异常消息:
“无法创建类型为 JsonSerializationExample.ISample 的实例。类型是一个接口或抽象类,不能即时化。
如果我派生了一个 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 方法进行编码以使序列化再次工作。
有人可以帮忙吗?
这是解决问题的“正确”方法吗?
你不需要使用 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());
文档:使用 CustomCreationConverter 反序列化
它非常简单,并且 json.net 提供的开箱即用支持,您只需在序列化和反序列化时使用以下 JsonSettings:
JsonConvert.SerializeObject(graph,Formatting.None, new JsonSerializerSettings()
{
TypeNameHandling =TypeNameHandling.Objects,
TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple
});
对于反序列化,请使用以下代码:
JsonConvert.DeserializeObject(Encoding.UTF8.GetString(bData),type,
new JsonSerializerSettings(){TypeNameHandling = TypeNameHandling.Objects}
);
只需记下 JsonSerializerSettings 对象初始值设定项,这对您很重要。
我通过使用 JsonSerializerSettings 的特殊设置解决了这个问题,该设置称为 TypeNameHandling.All
类型名称处理设置包括序列化 JSON 时的类型信息和读取类型信息,以便在反序列化 JSON 时创建创建类型
序列化:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var text = JsonConvert.SerializeObject(configuration, settings);
反序列化:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var configuration = JsonConvert.DeserializeObject<YourClass>(json, settings);
类 YourClass 可能具有任何类型的基类型字段,它将正确序列化。