[英]Deserialize nested ICollection<BaseType> in Asp.Net Web API 2 controller
I have a Web Api Controller like this one : 我有一个像这样的Web Api控制器:
public IHttpActionResult Create(PaymentDTO Payment)
My DTOs are: 我的DTO是:
public class PaymentDTO
{
public int Id { get; set; }
public string type { get; set; }
public IEnumerable<TransactionDTO> Transactions { get; set; }
}
public class TransactionDTO
{
public int Id { get; set; }
public string Description { get; set; }
public string CreateTime { get; set; }
public string UpdateTime { get; set; }
}
public class SaleDTO : TransactionDTO
{
public string Total { get; set; }
public string Currency{ get; set; }
}
public class OrderDTO : TransactionDTO
{
public string State {get;set;}
}
I receive the following JSON formatted data : 我收到以下JSON格式的数据:
{ "Type": "sale", "Id": 101, "transactions": [ { "Total": "30.50", "Currency": "USD", "Description": "transaction description" } ] }
I want JSON.net to instantiate either a IEnumerable<SaleDTO>
or IEnumerable<OrderDTO>
based on the Type
Property. 我希望JSON.net根据
Type
属性实例化IEnumerable<SaleDTO>
或IEnumerable<OrderDTO>
。
I could've used a custom type converter, but only if Type
property was in TransactionDTO
. 我可以使用自定义类型转换器,但前提是
Type
属性位于TransactionDTO
。 But I want the Type
property to be in the parent object ( PaymentDTO
) 但我希望
Type
属性位于父对象( PaymentDTO
)中
Thank you in advance for your help. 预先感谢您的帮助。
You can do this with a custom JsonConverter
on the PaymentDTO
class: 您可以使用
PaymentDTO
类上的自定义JsonConverter
来做到这一点:
public class PaymentDTOConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(PaymentDTO).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var obj = JObject.Load(reader);
var payment = (PaymentDTO)existingValue ?? new PaymentDTO();
// Extract the transactions.
var transactions = obj.Property("transactions") ?? obj.Property("Transactions");
if (transactions != null)
transactions.Remove();
// Populate the remaining regular properties.
using (var subReader = obj.CreateReader())
serializer.Populate(subReader, payment);
if (transactions != null)
{
// Deserialize the transactions list.
var type = PaymentDTO.GetTransactionDTOType(payment.type) ?? typeof(TransactionDTO);
using (var subReader = transactions.Value.CreateReader())
// Here we are taking advantage of array covariance.
payment.Transactions = (IEnumerable<TransactionDTO>)serializer.Deserialize(subReader, type.MakeArrayType());
}
return payment;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then apply it to your PaymentDTO
class as follows: 然后将其应用于您的
PaymentDTO
类,如下所示:
[JsonConverter(typeof(PaymentDTOConverter))]
public class PaymentDTO
{
static Dictionary<string, Type> namesToTransactions;
static Dictionary<Type, string> transactionsToNames = new Dictionary<Type, string>
{
{ typeof(SaleDTO), "sale" },
{ typeof(OrderDTO), "order" },
};
static PaymentDTO()
{
namesToTransactions = transactionsToNames.ToDictionary(p => p.Value, p => p.Key);
}
public static string GetTransactionDTOTypeName<TTransactionDTO>() where TTransactionDTO : TransactionDTO
{
string name;
if (transactionsToNames.TryGetValue(typeof(TTransactionDTO), out name))
return name;
return null;
}
public static Type GetTransactionDTOType(string name)
{
Type type;
if (namesToTransactions.TryGetValue(name, out type))
return type;
return null;
}
public int Id { get; set; }
public string type { get; set; }
[JsonProperty("transactions")]
public IEnumerable<TransactionDTO> Transactions { get; set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.