How to deserialize collection with different types?

后端 未结 1 690
无人及你
无人及你 2021-01-17 21:47

I have a JSON feed that looks like this (I removed some fields that aren\'t necessary for this example):

{
  \"total_count\": 2,
  \"num_pages\": 1,
  \"curr         


        
相关标签:
1条回答
  • 2021-01-17 22:14

    Your question is essentially a duplicate of this one, and the solution is the same. You need a JsonConverter to instantiate the correct object. However, there are a couple of differences that I see.

    If you look at the converter implementation from the other answer, you can see that it looks for a boolean flag in the JSON to determine the type to instantiate. In your case, there is not such a flag, so you'd need to use the existence or absence of a field to make this determination. Also, your list of transactions in the JSON is actually a list of objects that contain transactions, so the converter needs to account for that as well.

    With these changes, your converter should look something like this:

    public class TransactionConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(Transaction).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, 
            Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken transaction = JToken.Load(reader)["transaction"];
            if (transaction["recipient"] != null)
            {
                return transaction.ToObject<InternalTransaction>();
            }
            else
            {
                return transaction.ToObject<ExternalTransaction>();
            }
        }
    
        public override void WriteJson(JsonWriter writer, 
            object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    assuming that your classes are defined like this:

    class TransactionPagedResult
    {
        [JsonProperty(ItemConverterType=typeof(TransactionConverter))]
        public IEnumerable<Transaction> Transactions { get; set; }
    }
    
    class Transaction
    {
        public string Id { get; set; }
        [JsonProperty("created_at")]
        public DateTime CreatedAt { get; set; }
    }
    
    class InternalTransaction : Transaction
    {
        public User Recipient { get; set; }
    }
    
    class ExternalTransaction : Transaction
    {
        public string Hsh { get; set; }
        [JsonProperty("recipient_address")]
        public string RecipientAddress { get; set; }
    }
    
    class User
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }
    

    Also, to answer the last part of your question, if you decorate your list with a [JsonConverter] attribute, the converter is expected to handle the entire list. To handle the individual items, you need to use [JsonProperty(ItemConverterType=typeof(TransactionConverter))] on the list instead. I've edited the class definitions above to make this clear.

    0 讨论(0)
提交回复
热议问题