小编典典

将JSON反序列化为抽象类

c#

我正在尝试将JSON字符串反序列化为具体类,该具体类继承自抽象类,但是我无法使其正常工作。我已经在Google上搜索并尝试了一些解决方案,但它们似乎也不起作用。

这就是我现在所拥有的:

abstract class AbstractClass { }

class ConcreteClass { }

public AbstractClass Decode(string jsonString)
{
    JsonSerializerSettings jss = new JsonSerializerSettings();
    jss.TypeNameHandling = TypeNameHandling.All;
    return (AbstractClass)JsonConvert.DeserializeObject(jsonString, null, jss);
}

但是,如果我尝试强制转换结果对象,那将是行不通的。

我不使用DeserializeObject的原因是我有 许多具体的类

有什么建议么?

  • 我正在使用Newtonsoft.Json

阅读 1155

收藏
2020-05-19

共1个答案

小编典典

一个人可能不想使用TypeNameHandling(因为一个人想要更紧凑的json或想为类型变量使用一个特定的名称而不是“ $
type”)。同时,如果一个人想要将基类反序列化为多个派生类中的任何一个而不事先知道要使用哪个类,则customerCreationConverter方法将不起作用。

一种替代方法是在基类中使用int或其他类型并定义JsonConverter。

[JsonConverter(typeof(BaseConverter))]
abstract class Base
{
    public int ObjType { get; set; }
    public int Id { get; set; }
}

class DerivedType1 : Base
{
    public string Foo { get; set; }
}

class DerivedType2 : Base
{
    public string Bar { get; set; }
}

然后,基类的JsonConverter可以根据对象的类型反序列化该对象。复杂之处在于,为了避免堆栈溢出(JsonConverter反复调用其自身),必须在此反序列化期间使用自定义合同解析器。

public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
    protected override JsonConverter ResolveContractConverter(Type objectType)
    {
        if (typeof(Base).IsAssignableFrom(objectType) && !objectType.IsAbstract)
            return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
        return base.ResolveContractConverter(objectType);
    }
}

public class BaseConverter : JsonConverter
{
    static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() };

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Base));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        switch (jo["ObjType"].Value<int>())
        {
            case 1:
                return JsonConvert.DeserializeObject<DerivedType1>(jo.ToString(), SpecifiedSubclassConversion);
            case 2:
                return JsonConvert.DeserializeObject<DerivedType2>(jo.ToString(), SpecifiedSubclassConversion);
            default:
                throw new Exception();
        }
        throw new NotImplementedException();
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException(); // won't be called because CanWrite returns false
    }
}

而已。现在,您可以使用序列化/反序列化任何派生类。您还可以在其他类中使用基类,并对其进行序列化/反序列化,而无需任何其他工作:

class Holder
    {
        public List<Base> Objects { get; set; }
    }
string json = @"
        [
            {
                ""Objects"" : 
                [
                    { ""ObjType"": 1, ""Id"" : 1, ""Foo"" : ""One"" },
                    { ""ObjType"": 1, ""Id"" : 2, ""Foo"" : ""Two"" },
                ]
            },
            {
                ""Objects"" : 
                [
                    { ""ObjType"": 2, ""Id"" : 3, ""Bar"" : ""Three"" },
                    { ""ObjType"": 2, ""Id"" : 4, ""Bar"" : ""Four"" },
                ]
            },
        ]";

            List<Holder> list = JsonConvert.DeserializeObject<List<Holder>>(json);
            string serializedAgain = JsonConvert.SerializeObject(list);
            Debug.WriteLine(serializedAgain);
2020-05-19