使用 System.Text.JSON 不支持反序列化接口类型
Deserialization of inteface types not supported using System.Text.JSON
我正在将一个有效的 JSON 对象传递到我的 .net core 3 web api 应用程序上的控制器。这样做,我得到错误:
System.NotSupportedException: Deserialization of interface types is not supported. Type '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 反序列化器在尝试转换它时抛出了错误。那么我该如何克服这个错误呢?我受接口的具体实现的约束,所以如果可能的话,我无法更改我需要使用我在这里拥有的接口。如果那不可能,是否有任何 "work arounds" 用于此?
这里:
public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }
您的列表属于 IImportOrderLineModel
接口类型。
应该是
public List<ImportOrderLineModel> Lines { get; set; }
ImportOrderLineModel
是一个 class,它的实现方式如下:
public class ImportOrderLineModel : IImportOrderLineModel
{
//......
}
我和 HttpClient.GetFromJsonAsync
有同样的问题
我试过了 httpClient.GetFromJsonAsync<ICustomer>(url);
我得到了错误:
Deserialization of inteface types not supported using System.Text.JSON
据我所知,模型必须可用于反序列化 InterfaceType。
我的解决方案使用数据注释在界面中定义模型。
创建一个 TypeConverter(我在这里找到这个 class: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<AddressModel>))]
)
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);
我正在将一个有效的 JSON 对象传递到我的 .net core 3 web api 应用程序上的控制器。这样做,我得到错误:
System.NotSupportedException: Deserialization of interface types is not supported. Type '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 反序列化器在尝试转换它时抛出了错误。那么我该如何克服这个错误呢?我受接口的具体实现的约束,所以如果可能的话,我无法更改我需要使用我在这里拥有的接口。如果那不可能,是否有任何 "work arounds" 用于此?
这里:
public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }
您的列表属于 IImportOrderLineModel
接口类型。
应该是
public List<ImportOrderLineModel> Lines { get; set; }
ImportOrderLineModel
是一个 class,它的实现方式如下:
public class ImportOrderLineModel : IImportOrderLineModel
{
//......
}
我和 HttpClient.GetFromJsonAsync
有同样的问题
我试过了 httpClient.GetFromJsonAsync<ICustomer>(url);
我得到了错误:
Deserialization of inteface types not supported using System.Text.JSON
据我所知,模型必须可用于反序列化 InterfaceType。 我的解决方案使用数据注释在界面中定义模型。
创建一个 TypeConverter(我在这里找到这个 class: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<AddressModel>))]
)
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);