如何将子实例反序列化为父对象而不丢失其特定属性?

时间:2015-01-19 14:03:06

标签: c# json json.net

以下是几个课程。如何序列化A实例的Json字符串,其中PropertyB包含SpecPropB1或SpecPropB2,以便这些属性保留在C#对象中?

public class A
{
  public B PropertyB {get;set;}
}

public class B
{
  public string GenProp {get;set;}
}

public class B1:B
{
  public string SpecPropB1 {get;set;}
}

public class B2:B
{
  public string SpecPropB2 {get;set;}
}

我看到了这个问题的多种解决方案,但它们缺乏优雅:

  • 将propertyB的类型作为对象:我失去了此属性的强类型。
  • 将有问题的部分重新序列化为子对象:这将很快变得丑陋
  • 创建一个特定的类ASerialisable(具有B1和B2属性),将字符串序列化为此,然后使用构造函数从此类创建一个A对象:与上面相同,我担心它会创建很多类如果有很多类似的问题。 *在序列化之前添加对象的类型,并使用属性TypeNameHandling。我没有看到一种不涉及部分反序列化的方法。

类似的问题,但我也不是序列化字符串的那个,所以我不能使用这个解决方案: Deserialize into correct child objects

修改

我创建了一个继承JSonConverter的新类,它自动完成了Falanwe提出的工作。 这是需要它的人的最终代码。

private class BConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(A).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        if(objectType.IsSubclassOf(typeof(B)) || objectType == typeof(B))
        {
            if (item["SpecPropB1"] != null)
            {
                return new B1() 
                { 
                    GenProp = (string)item["GenProp"], 
                    SpecPropB1 = (string)item["SpecPropB1"] 
                };
            }
            else if (item["SpecPropB2"] != null)
            {
                return new B2()
                {
                    GenProp = (string)item["GenProp"],
                    SpecPropB2 = (string)item["SpecPropB2"]
                };
            }
            else
            {
                return new B()
                {
                    GenProp = (string)item["GenProp"]
                };
            }
        }
        else
        {
            return item.ToObject(objectType);
        }
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        //not implemented here but needed if you want to deserialized data,
        // this can help you: http://blog.maskalik.com/asp-net/json-net-implement-custom-serialization/
        throw new NotImplementedException();
    }
}

private class A
{

    public B PropertyB { get; set; }
}

[JsonConverter(typeof(BConverter))]
private class B
{
    public string GenProp { get; set; }
}

private class B1 : B
{
    public string SpecPropB1 { get; set; }
}

private class B2 : B
{
    public string SpecPropB2 { get; set; }
} 

0 个答案:

没有答案