2016-03-28 14 views
0

2 kontrolör: Deserialize iç içe ıcollection <BaseType> bunun gibi bir Web Api Denetleyicisi sahip

public IHttpActionResult Create(PaymentDTO Payment) 

Benim DTOs

şunlardır:

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

aşağıdaki JSON formatlı veri almak :

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

JSON.net'in veya Mülklerini temel alan IEnumerable<OrderDTO> örneğini başlatmasını istiyorum.

Özel bir tür dönüştürücü kullanabiliyordum, ancak yalnızca Type özelliği TransactionDTO içeriyordu. Ancak, Type özelliğinin üst nesnede olmasını (PaymentDTO)

Yardımlarınız için şimdiden teşekkür ederiz.

Sen PaymentDTO sınıfı bir custom JsonConverter ile yapabilirsiniz

cevap

1

: Sonra

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(); 
    } 
} 

sizin PaymentDTO sınıfa uygulamak aşağıdaki gibi:

[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; } 
} 
İlgili konular