C# 反序列化具有抽象类型属性的对象

C# 反序列化具有抽象类型属性的对象,c#,asp.net-core,.net-core,json.net,C#,Asp.net Core,.net Core,Json.net,我有一个例子,我需要反序列化一个json文件,但在某些情况下有一个属性略有不同。以下是一个例子: [ { "NameProperty": "ex1", "OtherProperty":"example", "DifferentProperty": "here is a string value" }, { "NameProperty": "ex1", "OtherProperty":"exam

我有一个例子,我需要反序列化一个json文件,但在某些情况下有一个属性略有不同。以下是一个例子:

[
    {
        "NameProperty": "ex1",
        "OtherProperty":"example",
        "DifferentProperty": "here is a string value"
    },
    {
        "NameProperty": "ex1",
        "OtherProperty":"example",
        "DifferentProperty": ["here", "is", "an" "array"]
    },
    {
        "NameProperty": "ex1",
        "OtherProperty":"example",
        "DifferentProperty": 234 //number
    }
]
下面是这些json的模型:

抽象类属性库 { }

class StringProperty:PropertyBase
{
公共字符串值{get;set;}
}
类ArrayProperty:PropertyBase
{
公共IList值{get;set;}
}
类号属性:PropertyBase
{
公共双值{get;set;}
}
类示例模型
{
公共字符串名称属性{get;set;}
公共字符串属性
{
获得;设置;
}
公共属性数据库差异属性{get;set;}
}
然后我想将对象列表传递给asp.net核心控制器函数,例如:

public IActionResult ExampleFunction([FromBody] List<ExampleModel> request){ }
publicIActionResult示例函数([FromBody]列表请求){

这里有一个问题,因为我知道如何反序列化派生类列表,但我不知道如何反序列化具有抽象类型属性的对象。我想编写一个JsonConvert类,它将被传递到asp.net mvc config。

我只想跳过整个PropertyBase,为什么不为ExampleModel创建一个解析程序,它可以执行以下操作:

class ExampleModel
{
    public string NameProperty { get; set; }
    public string OtherProperty { get; set; }
    public object DifferentProperty { get; set; }

    public string DifferentPropertyString { get; set; }
    public string[] DifferentPropertyStringArray { get; set; }
    public int DifferentPropertyInt { get; set; }

    private void ResolveDifferentProperty()
    {
        // Try to resolve the DifferentProperty property with a converter or 
        //something similar into one of your three specific "DifferentProperty"'s?
    }
}

class Program
{
    public void Main(string[] args)
    {
        var model = JsonConvert.DeserializeObject<ExampleModel>(jsonData);
        model.ResolveDifferentProperty();
    }
}
类示例模型
{
公共字符串名称属性{get;set;}
公共字符串OtherProperty{get;set;}
公共对象差异属性{get;set;}
公共字符串DifferentPropertyString{get;set;}
公共字符串[]DifferentPropertyStringArray{get;set;}
公共int-DifferentPropertyInt{get;set;}
私有void ResolvedDifferentProperty()
{
//尝试使用转换器或
//类似于你的三个“不同属性”中的一个?
}
}
班级计划
{
公共void Main(字符串[]参数)
{
var model=JsonConvert.DeserializeObject(jsonData);
model.ResolveDifferentProperty();
}
}
为了知道哪个属性已解析为,可以让ExampleModel包含DifferentPropertyEnum属性或其他内容,以便您知道哪个属性已从解析中填充。你明白了

另外,请记住,在编译时您无法知道这到底是什么类型的属性。你不能用var关键字或类似的东西访问它,所以如果你想经常使用它,你必须经常打开这个属性

当然,您可以通过将DifferentProperty对象设置为动态对象(字面上是使用dynamic关键字)来绕过这个问题。这不会生成编译器警告,但如果您不小心,它会使运行时崩溃。当然,这被认为是更不安全的,但假设您的控制器只想将其存储在varchar数据库字段或其他内容中,那么我可能会使用动态

公共类ExampleModelConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
serializer.Serialize(writer,value);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var token=JToken.Load(读卡器);
var name=token[“NameProperty”].ToString();
PropertyBase prop=null;
//比如说,你该怎么做取决于你自己
//创建PropertyBase的实例
交换机(名称)
{
大小写“string”:prop=newstringproperty();
打破
案例“number”:prop=newnumberproperty();
打破
案例“array”:prop=newarrayProperty();
打破
}
var ex=新的ExampleModel
{
差异属性=属性
};
序列化程序。填充(读卡器,ex);
退换货;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回typeof(ExampleModel)==objectType;
}
}
[JsonConverter(类型(PropertyConverter))]
类示例模型
{
公共字符串名称属性{get;set;}
公共字符串属性
{
获得;设置;
}
公共属性数据库差异属性{get;set;}
}
班级计划
{
公共void Main(字符串[]参数)
{
var model=JsonConvert.DeserializeObject(jsonData);
}
}

因为抽象类不是实例化的hanks,所以这就是我要找的!:)我走上了正轨,但你启发了我:)
class ExampleModel
{
    public string NameProperty { get; set; }
    public string OtherProperty { get; set; }
    public object DifferentProperty { get; set; }

    public string DifferentPropertyString { get; set; }
    public string[] DifferentPropertyStringArray { get; set; }
    public int DifferentPropertyInt { get; set; }

    private void ResolveDifferentProperty()
    {
        // Try to resolve the DifferentProperty property with a converter or 
        //something similar into one of your three specific "DifferentProperty"'s?
    }
}

class Program
{
    public void Main(string[] args)
    {
        var model = JsonConvert.DeserializeObject<ExampleModel>(jsonData);
        model.ResolveDifferentProperty();
    }
}
public class ExampleModelConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        var name = token["NameProperty"].ToString();
        PropertyBase prop = null;
        // for example, it is up to you how you
        // create an instance of PropertyBase
        switch (name)
        {
            case "string" : prop = new StringProperty();
                break;
            case "number" : prop = new NumberProperty();
                break;
            case "array" : prop = new ArrayProperty();
                break;
        }

        var ex = new ExampleModel
        {
            DifferentProperty = prop
        };
        serializer.Populate(reader, ex);
        return ex;
    }

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

[JsonConverter(typeof(PropertyConverter))]
class ExampleModel
{
    public string NameProperty { get; set; }
    public string OtherProperty
    {
        get; set;
    }
    public PropertyBase DifferentProperty { get; set; }
}

class Program
{
    public void Main(string[] args)
    {
        var model = JsonConvert.DeserializeObject<ExampleModel>(jsonData);
    }
}