I am passing in a valid JSON object to my controller on my .net core 3 web api application. Doing so, I get the error:
System.NotSupportedException: Deserialization of interface types is not supported. Type 'OrderTranslationContracts.OrderContracts+IImportOrderLineModel'
So I looked in my code and I have the following concrete implementation of an Interface. Here is the line I think that's throwing the error:
public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }
Here is the portion of the JSON I am passing into the controller:
"lines": [
{
"orderNumber": "LV21131327",
"lineNumber": 1,
"itemId": "3083US",
"customerItemId": "3083US",
"quantity": 3,
"price": 0.00,
"quantityBackOrdered": null,
"comments": "",
"pickLocation": "",
"orderFilled": "O",
"hostUom": null,
"type": null
}
So I know the JSON is valid. Here is the signature for the controller:
[HttpPost]
public async Task<List<ImportOrderModel>> Post([FromBody] List<ImportOrderModel> orders)
{
var response = await _validateOrder.ValidateAllOrdersAsync(orders, null);
return response;
}
I don't even break into this code as I am assuming that the JSON deserializer is throwing the error as it tries to convert it. So how do I over come this error? I am bound by the concrete implementation for the interface so I can't change the interface I need to work with what I have here if possible. If that isn't possible, are there any "work arounds" for this?
Text. Json doesn't support the serialization of polymorphic type hierarchies. For example, if a property's type is an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties.
A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.
Text. Json. Serialization namespace, which contains attributes and APIs for advanced scenarios and customization specific to serialization and deserialization.
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
I had the same problems with HttpClient.GetFromJsonAsync
I tried httpClient.GetFromJsonAsync<ICustomer>(url);
And I got the error:
Deserialization of inteface types not supported using System.Text.JSON
From what I was able to find out, a model has to be available to deserialize an InterfaceType. My solution defines the model in the interface using data annotations.
Create a TypeConverter (I found this class here: Casting interfaces for deserialization in JSON.NET)
using 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 Add Data Annotations in your Interface ([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 Unfortunatly HttpClient.GetFromJsonAsync
does not use Newtonsoft. I wrote my own method
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 Now i can use:
HttpClient httpClient= new HttpClient();
string url="https://example.com/api/customerlist";
var myCustomerList[]=await GetJsonAsync<CutomerModel[]>(httpClient, url);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With