【问题标题】:Deserialization of inteface types not supported using System.Text.JSON不支持使用 System.Text.JSON 对接口类型进行反序列化
【发布时间】:2019-12-05 20:47:21
【问题描述】:

我正在向我的 .net core 3 web api 应用程序上的控制器传递一个有效的 JSON 对象。这样做,我得到了错误:

System.NotSupportedException:不支持接口类型的反序列化。输入“OrderTranslationContracts.OrderContracts+IImportOrderLineModel”

所以我查看了我的代码,我有以下具体的接口实现。这是我认为引发错误的那一行:

   public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }

这是我传递给控制器​​的 JSON 部分:

"lines": [
        {
            "orderNumber": "LV21131327",
            "lineNumber": 1,
            "itemId": "3083US",
            "customerItemId": "3083US",
            "quantity": 3,
            "price": 0.00,
            "quantityBackOrdered": null,
            "comments": "",
            "pickLocation": "",
            "orderFilled": "O",
            "hostUom": null,
            "type": null
        }

所以我知道 JSON 是有效的。这是控制器的签名:

[HttpPost]
    public async Task<List<ImportOrderModel>> Post([FromBody] List<ImportOrderModel> orders)
    {
        var response = await _validateOrder.ValidateAllOrdersAsync(orders, null);
        return response;
    }

我什至没有闯入这段代码,因为我假设 JSON 反序列化器在尝试转换它时抛出了错误。那么我该如何克服这个错误呢?我受接口的具体实现的约束,所以如果可能的话,我无法更改我需要使用的接口。如果这不可能,是否有任何“解决方法”?

【问题讨论】:

    标签: c# json deserialization system.text.json


    【解决方案1】:

    HttpClient.GetFromJsonAsync 我也遇到了同样的问题 我试过httpClient.GetFromJsonAsync&lt;ICustomer&gt;(url);

    我得到了错误:

    不支持使用 System.Text.JSON 的接口类型的反序列化

    据我所知,必须有一个模型可用于反序列化 InterfaceType。 我的解决方案使用数据注释在接口中定义模型。

    1. 创建一个 TypeConverter(我在这里找到了这个类:Casting interfaces for deserialization in JSON.NET

      使用 Newtonsoft.Json;

      public class ConcreteTypeConverter<TConcrete> : JsonConverter
       {
           public override bool CanConvert(Type objectType)
           {
               //assume we can convert to anything for now
               return true;
           }
      
           public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
           {
               //explicitly specify the concrete type we want to create
               return serializer.Deserialize<TConcrete>(reader);
           }
      
           public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
           {
               //use the default serialization - it works fine
               serializer.Serialize(writer, value);
           }
       }
      

    2 在您的界面中添加数据注释 ([JsonConverter(typeof(ConcreteTypeConverter&lt;AddressModel&gt;))])

    using Newtonsoft.Json;
    public interface ICustomer
    {
        int Id { get; set; }
        int Name { get; set; }
    
        [JsonConverter(typeof(ConcreteTypeConverter<AddressModel>))]
        IAddress Address { get; set; }
    }
    

    3 不幸的是 HttpClient.GetFromJsonAsync 不使用 Newtonsoft。我自己写了方法

    public async static Task<T> GetJsonAsync<T>(HttpClient client, string url)
    {
        using var response = await client.GetAsync(url);
        response.EnsureSuccessStatusCode();
    
        using Stream stream = await response.Content.ReadAsStreamAsync();
        using (var reader = new StreamReader(stream, Encoding.UTF8))
        {
            return JsonConvert.DeserializeObject<T>(reader.ReadToEnd(), new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                NullValueHandling= NullValueHandling.Ignore
            });
        }
    }
    

    4 现在我可以使用了:

     HttpClient httpClient= new HttpClient();
     string url="https://example.com/api/customerlist";
     var myCustomerList[]=await GetJsonAsync<CutomerModel[]>(httpClient, url);
    

    【讨论】:

      【解决方案2】:

      这里:

      public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }
      

      您的列表类型为IImportOrderLineModel Interface。

      应该是这样的

       public List<ImportOrderLineModel> Lines { get; set; }
      

      ImportOrderLineModel 是一个实现它的类:

      public class ImportOrderLineModel : IImportOrderLineModel
      {
          //......
      }
      

      【讨论】:

      • OP 应该使用 JsonConverter 将接口映射到具体类型。以这种方式使用具体实现,这违背了接口的目的(并且违反了 SOLID)。
      • 谢谢我把它放进去,它能够克服错误。
      • 这只是一种解决方法,并不能解决问题。请使用@user12447201 他的解决方案
      猜你喜欢
      • 2020-04-06
      • 2021-12-01
      • 1970-01-01
      • 2019-10-07
      • 2014-06-30
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      相关资源
      最近更新 更多