【问题标题】:Create child type during deserialization在反序列化期间创建子类型
【发布时间】:2014-02-22 21:31:22
【问题描述】:

我得到了以下 JSON 文档:

{
    "Title": "jkdjdjd",
    "Description": "dkfkkdd",
    "Actions": [{
                    "ActionType": "Email",
                    "Subject": "Bkdfkdk",
                    "Body": "kddkdkkd"
                }, {
                    "ActionType": "SMS",
                    "PhoneNumber": "+46333333"
                }
    ]
}

我的课程如下所示:

public class Trigger
{
    public string Name { get; set; }
    public string Description { get; set; }
    public List<Action> Actions { get; set; }
}


public class Action
{
    public string ActionType { get; set; }
}

public class EmailAction : Action
{
    public string Subject { get; set; }
    public string Body { get; set; }
}

public class SmsAction : Action
{
    public string PhoneNumber { get; set; }
}

所以我基本上想要的是让 JSON.NET 根据“ActionType”中的名称选择子类的类型。我知道 JSON.NET 支持一个可以用来识别子类的特殊字段。但我宁愿让友好的名称控制生成哪个类。

我发现我应该使用CustomCreationConverter&lt;Action&gt; 进行选择。但我无法弄清楚如何在不搞砸实际反序列化的情况下读取该字段。

如果有帮助,我可以改用以下布局:

public class Action
{
    public string ActionType { get; set; }
    public ActionData Data { get; set; }
}

public ActionData
{
}

public class EmailData : ActionData
{
    public string Subject { get; set; }
    public string Body { get; set; }
}

public class SmsData : ActionData
{
    public string PhoneNumber { get; set; }
}

即JSON 将是:

{
    "Title": "jkdjdjd",
    "Description": "dkfkkdd",
    "Actions": [{
                    "ActionType": "Email",
                    "Data": {
                        "Subject": "Bkdfkdk",
                        "Body": "kddkdkkd"
                    }
                }, {
                    "ActionType": "SMS",
                    "Data": {
                        "PhoneNumber": "+46333333"
                    }
                }
    ]
}

【问题讨论】:

  • 没有回答您的问题,但是在您的 JSON 根节点中,您拥有 Title 属性,而您的 Trigger 类拥有 Name 属性。我认为这些应该具有相同的属性名称。

标签: c# json.net asp.net-web-api2


【解决方案1】:

如果您不介意在 JSON 中包含 type 属性,您可以使用 JsonSerializer TypeNameHandling = TypeNameHandling.Auto 的设置。

否则,您可以创建自定义 JsonConverter 并将其添加到序列化期间使用的转换器列表中。这篇文章中有一个很好的例子,对我来说效果很好:

http://dotnetbyexample.blogspot.co.uk/2012/02/json-deserialization-with-jsonnet-class.html

编辑:

这不是按预期对您有用吗? 您是否尝试过将 Action 基类抽象化?

您在 CreationConverter 方面尝试过什么?它究竟是如何不起作用的 - 你能提供一些细节吗?

public class JsonActionConverter : JsonCreationConverter<Action>
  {
    protected override Action Create(Type objectType, JObject jsonObject)
    {
      var typeName = jsonObject["ActionType"].ToString();
      switch(typeName)
      {
        case "Email":
          return new EmailAction();
        case "SMS":
          return new SMSAction();
        default: return null;
      }
    }
  }

【讨论】:

  • 只需填写完成您的答案所需的JsonConverter。否则它只是一个评论。
  • 阅读我的问题的中间部分。你说的我已经解决了
  • @jgauffin - 查看我的编辑并发布一些关于错误/意外行为的详细信息,如果这不能解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多