2016-03-28 10 views
0

私はこの1つのようなWebアピコントローラーている:私のDTOはデシリアライズネストされたICollectionをAsp.NetのWeb APIで<BaseType> 2コントローラ

public IHttpActionResult Create(PaymentDTO Payment) 

のとおりです。

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" 
    } 
    ] 
} 

Typeプロパティに基づいてIEnumerable<SaleDTO>またはIEnumerable<OrderDTO>のいずれかをJSON.netでインスタンス化します。

TransactionDTOTypeプロパティがある場合に限り、カスタムタイプコンバータを使用できました。しかし、Typeプロパティが親オブジェクトにあるようにしたい(PaymentDTO

ありがとうございました。あなたがPaymentDTOクラスにcustom JsonConverterでこれを行うことができます

答えて

1

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; } 
} 
関連する問題