如何反序列化收集不同类型的? [英] How to deserialize collection with different types?

查看:210
本文介绍了如何反序列化收集不同类型的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JSON提要看起来像这样(我删除了一些字段是没有必要在这个例子中):

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,
  "current_page": 1,
  "balance": {
    "amount": "0.00001199",
    "currency": "BTC"
  },
  "transactions": [
    {
      "transaction": {
        "id": "5018f833f8182b129c00002f",
        "created_at": "2012-08-01T02:34:43-07:00",
        "sender": {
          "id": "5011f33df8182b142400000e",
          "name": "User Two",
          "email": "user2@example.com"
        },
        "recipient": {
          "id": "5011f33df8182b142400000a",
          "name": "User One",
          "email": "user1@example.com"
        }
      }
    },
    {
      "transaction": {
        "id": "5018f833f8182b129c00002e",
        "created_at": "2012-08-01T02:36:43-07:00",
        "hsh": "9d6a7d1112c3db9de5315b421a5153d71413f5f752aff75bf504b77df4e646a3",
        "sender": {
          "id": "5011f33df8182b142400000e",
          "name": "User Two",
          "email": "user2@example.com"
        },
        "recipient_address": "37muSN5ZrukVTvyVh3mT5Zc5ew9L9CBare"
      }
    }
 ]
}

有两种类型的这种饲料交易:有一个收件人内部交易和外部交易有一个 HSH RECIPIENT_ADDRESS

There are two types of transactions in this feed: internal transactions that have a recipient, and external transactions that have a hsh and recipient_address.

我创建了下面的类,以适应这种结构:

I created the following classes to accomodate this structure:

因此​​,我们必须对所有的基类分页的结果( PagedResult )与特定实现交易(TransactionPagedResult <$ C C $> )。该结果包含0 .. *交易集合(抽象类交易)。他们的类型并不交易不过,但类型的 InternalTransaction ExternalTransaction 这是交易的实现。

So we have a base class for all paged results (PagedResult) with a specific implementation for transactions (TransactionPagedResult). This result has a collection containing 0..* transactions (abstract class Transaction). They're not of the type Transaction though, but of type InternalTransaction or ExternalTransaction which are implementations of Transaction.

我的问题是我怎么可以让JSON.NET处理这个问题。我想JSON.NET看到当前事务它的解析是否是 InternalTransaction ExternalTransaction ,并根据该加键入到的IEnumerable&LT;交易&GT; 集合 TransactionPagedResult

My question is how I can let JSON.NET handle this. I want JSON.NET to see whether the current transaction it's parsing is an InternalTransaction or an ExternalTransaction, and add the according type to the IEnumerable<Transaction> collection in TransactionPagedResult.

我创造了我添加为一个属性,我自己JsonConverter的的IEnumerable&LT;交易&GT; [JsonConverter(typeof运算(TransactionCreationConverter))] 属性,但这并没有工作,我得到以下错误:

I created my own JsonConverter that I added as a property to the IEnumerable<Transaction> with the [JsonConverter(typeof(TransactionCreationConverter))] attribute, but this didn't work, I get the following error:

更多信息:错误从JsonReader阅读JObject。当前   JsonReader产品不是一个对象:StartArray。路径'交易',   1号线,位置218。

Additional information: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path 'transactions', line 1, position 218.

据我所知,这是因为JSON.NET试图反序列化整个集合,但我想它由一个反序列化集合中的一个内部的每个对象。

I understand this is because JSON.NET tries to deserialize the whole collection, but I want it to deserialize each object inside the collection one by one.

有人吗?

推荐答案

您的问题本质上是这个的副本,并将该溶液是相同的。你需要一个 JsonConverter 实例化正确的对象。不过,也有几个,我看到的差异。

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.

如果你从对方回答转换器实现,你可以看到它寻找一个布尔标志JSON的确定类型来实例化。在你的情况下,有没有这样的标志,所以你需要使用一个字段的存在与否来做出判断。此外,您在JSON交易的名单实际上是的包含的交易对象的列表,所以转换器需要考虑到这一点。

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

此外,要回答你的问题的最后一部分,如果你装饰了 [JsonConverter] 属性的列表,该转换器预计将处理整个列表。为了处理单个项目,则需要使用 [JsonProperty(ItemConverterType = typeof运算(TransactionConverter))] 的列表,而不是上。我已经编辑上面的类定义,以明确这一点。

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.

这篇关于如何反序列化收集不同类型的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆