在<BaseType> Web API 2 控制器中反序列化嵌套 Asp.Net ICollection



我有一个像这样的Web Api控制器:

public IHttpActionResult Create(PaymentDTO Payment)

我的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;}
}

我收到以下JSON格式的数据:

{
  "Type": "sale",
  "Id": 101,
  "transactions": [
    {
      "Total": "30.50",
      "Currency": "USD",
      "Description": "transaction description"
    }
  ]
}

我希望JSON.net基于Type属性实例化IEnumerable<SaleDTO>IEnumerable<OrderDTO>

我本可以使用自定义类型转换器,但前提是Type属性在TransactionDTO中。但是我希望Type属性在父对象(PaymentDTO)中

提前感谢您的帮助。

您可以在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();
    }
}

然后将其应用于您的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; }
}

相关内容

  • 没有找到相关文章

最新更新