C# Newtonsoft:如何反序列化包含接口的接口,而不使用 Json 属性

C# Newtonsoft: How to deserialize an interface containing an interface, without Json attributes

提问人:Markus 提问时间:10/6/2023 最后编辑:Markus 更新时间:10/6/2023 访问量:37

问:

我有以下代码,它在最后一行中断,出现异常“无法创建 DeserializeInterfaces.IB 类型的实例”。如何在不使用 的情况下反序列化

[JsonProperty(ItemConverterType = typeof(ConcreteConverter<B>))]`  

属性?我不能使用这些属性,因为接口在不同的项目中,我不能在具体类上建立接口的循环依赖关系。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace DeserializeInterfaces
{
  public class CustomInterfaceConverter : JsonConverter
  {
    public override bool CanConvert( Type objectType )
    {
      bool convertible = typeof( IA ).IsAssignableFrom( objectType )
                         || typeof( IB ).IsAssignableFrom( objectType )                         
                         || typeof( A ).IsAssignableFrom( objectType )
                         || typeof( B ).IsAssignableFrom( objectType );
      return convertible;
    }

    public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
    {
      JObject jsonObject = JObject.Load( reader );

      // Determine the concrete type based on the JSON content
      if (objectType.Name == "IA")
      {
        A retVal = jsonObject.ToObject<A>( serializer );
        return retVal;
      }
      if (objectType.Name == "A")
      {
        A retVal = jsonObject.ToObject<A>();
        return retVal;
      }
      else if (objectType.Name == "IB")
      {
        B retVal = jsonObject.ToObject<B>( serializer );
        return retVal;
      }
      else if (objectType.Name == "B")
      {
        B retVal = jsonObject.ToObject<B>();
        return retVal;
      }
      // Handle other cases or return a default implementation
      return null;
    }
    public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
    {
      throw new NotImplementedException();
    }
  }
    
  public interface IA
  {
    IB b { get; set; }
  }

  public interface IB
  {
    int b { get; set; }
  }

  public class A : IA
  {
    [JsonConstructor]
    public A() { }

    public IB b { get; set; }
  }

  public class B : IB
  {
    [JsonConstructor]
    public B() { }

    public B( int pB )
    {
      b = pB;
    }
    
    public int b { get; set; }
  }

  class Program
  {    
    static void Main( string[] args )
    {
      CustomInterfaceConverter jsonConverter = new CustomInterfaceConverter();
      IA a = new A();
      a.b = new B(1);
      string aSer = JsonConvert.SerializeObject( a );

      A aDeser = JsonConvert.DeserializeObject<A>( aSer, jsonConverter );
    }
  }
}
嵌套 json.net 反序列化的 C# 接口

评论


答:

-1赞 Markus 10/6/2023 #1

在我删除了除 IB 之外的所有类型的 CanConvert 后,它起作用了,如下所示:

namespace DeserializeInterfaces
{
  public class CustomInterfaceConverter : JsonConverter
  {
    public override bool CanConvert( Type objectType )
    {
      bool convertible = typeof( IB ).IsAssignableFrom( objectType );

      return convertible;
    }

    public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
    {
      JObject jsonObject = JObject.Load( reader );
          
      if (objectType.Name == "IB")
      {
        B retVal = jsonObject.ToObject<B>();
        return retVal;
      }
      // Handle other cases or return a default implementation
      return null;
    }
    public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
    {
      throw new NotImplementedException();
    }
  }

  public interface IA
  {
    IB b { get; set; }
  }

  public interface IB
  {
    int b { get; set; }
  }

  public class A : IA
  {
    [JsonConstructor]
    public A() { }

    public IB b { get; set; }
  }

  public class B : IB
  {
    [JsonConstructor]
    public B() { }

    public B( int pB )
    {
      b = pB;
    }

    public int b { get; set; }
  }

  class Program
  {
    static void Main( string[] args )
    {
      CustomInterfaceConverter jsonConverter = new CustomInterfaceConverter();
      IA a = new A();
      a.b = new B( 1 );
      string aSer = JsonConvert.SerializeObject( a );

      A aDeser = JsonConvert.DeserializeObject<A>( aSer, jsonConverter );
    }
  }