在反序列化期间创建子类型

时间:2014-02-22 21:31:23

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

我收到了以下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; }
}

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

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

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

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

1 个答案:

答案 0 :(得分:2)

如果您不喜欢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;
      }
    }
  }