如何反序列化具有不同类型的集合?

列昂·卡伦斯(Leon Cullens)

我有一个看起来像这样的JSON提要(我删除了一些本示例不需要的字段):

{
  "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": "[email protected]"
        },
        "recipient": {
          "id": "5011f33df8182b142400000a",
          "name": "User One",
          "email": "[email protected]"
        }
      }
    },
    {
      "transaction": {
        "id": "5018f833f8182b129c00002e",
        "created_at": "2012-08-01T02:36:43-07:00",
        "hsh": "9d6a7d1112c3db9de5315b421a5153d71413f5f752aff75bf504b77df4e646a3",
        "sender": {
          "id": "5011f33df8182b142400000e",
          "name": "User Two",
          "email": "[email protected]"
        },
        "recipient_address": "37muSN5ZrukVTvyVh3mT5Zc5ew9L9CBare"
      }
    }
 ]
}

有两种类型的交易在这个饲料:有一个内部事务recipient有一个和外部交易hshrecipient_address

我创建了以下类来适应这种结构:

统一语言

因此,我们为所有分页结果(PagedResult)提供了基类,并为交易(TransactionPagedResult提供了特定的实现此结果具有一个包含0 .. *事务的集合(抽象类Transaction)。它们不是类型Transaction,而是类型InternalTransactionExternalTransaction的实现Transaction

我的问题是如何让JSON.NET处理此问题。我希望JSON.NET查看正在解析的当前事务是InternalTransaction还是an ExternalTransaction,然后将相应类型添加到中的IEnumerable<Transaction>集合中TransactionPagedResult

我创建了自己的JsonConverter,并将其作为属性添加到IEnumerable<Transaction>具有[JsonConverter(typeof(TransactionCreationConverter))]属性的,但这没有用,出现以下错误:

附加信息:从JsonReader读取JObject时出错。当前JsonReader项不是对象:StartArray。路径“交易”,第1行,位置218。

我了解这是因为JSON.NET尝试对整个集合进行反序列化,但是我希望它对集合中的每个对象进行逐一反序列化。

任何人?

布莱恩·罗杰斯(Brian Rogers)

您的问题本质上是问题的重复,解决方案是相同的。您需要一个JsonConverter实例化正确的对象。但是,我看到了一些区别。

如果您从另一个答案中查看转换器的实现,则可以看到它在JSON中寻找布尔标志来确定要实例化的类型。在您的情况下,没有这样的标志,因此您需要使用字段的存在或不存在来进行此确定。另外,您在JSON中的事务列表实际上是包含事务的对象列表,因此转换器也需要考虑这一点。

进行了这些更改后,您的转换器应如下所示:

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

假设您的类是这样定义的:

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))]列表。我已经编辑了上面的类定义以使其更加清楚。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在Jackson中反序列化具有相同名称但不同类型的属性?

反序列化可以具有不同类型的属性名称

从具有不同类型的HttpWebResponse GetResponseStream反序列化XML

反序列化具有不同类型的GenericObject <T>的列表

反序列化具有不同类型的JSON数组

具有不同类型的字段的 JSON 反序列化(使用 Jackson 和 Scala)

在C#中反序列化具有不同类型名称的XML元素

如何使用Retrofit / Gson在JSON中反序列化相同类型但具有不同字段名称的对象列表?

反序列化呈现为不同类型的节点

JavaScriptSerializer 反序列化不同类型的 Json 数组

如何在具有相同类型子节点的 c# 中反序列化 XML

使用 Spring WebClient,我如何反序列化不同类型的成功和失败响应?

如何在返回不同类型的同时反序列化 JSON?

如何反序列化具有两个名称相同但元素具有不同数据类型的XML?

C#JSON-序列化具有相同属性的不同类型的多个对象

为每个键值反序列化具有不同对象类型的JSON文件

使用 kotlinx.serialization 库反序列化具有不同值类型的 JSON 数组

如何序列化不同类型的字段?

如何将不同类型的子元素反序列化为基本类型的列表/集合,该列表/集合是相应类的属性

反序列化具有不同属性的 JSON

如何反序列化包含相同键名但使用不同类型的JSON文件(使用Google JSON)?

具有嵌入类型的反序列化JSON

如何反序列化具有包含不同对象的属性的json?

如何反序列化具有不同继承人的 JSON

JSON Newtonsoft C# 反序列化不同类型的对象列表

反序列化包含不同类型对象的JSON数组

GSON在Android中使用两种不同类型的对象反序列化列表

如何使用 serde 反序列化具有泛型类型的枚举

如何在Jackson中对具有抽象类型的引用进行反序列化JSON