提问者:小点点

NewtonSoft.Json 序列化和反序列化具有 IEnumerable <ISomeInterface>类型的属性的类


我正在尝试移动一些代码来使用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 方法进行编码以使序列化再次工作。

有人可以帮忙吗?

这是解决问题的“正确”方法吗?


共3个答案

匿名用户

你不需要使用 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 可能具有任何类型的基类型字段,它将正确序列化。