在某些情况下,我需要反序列化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的模型:
抽象类PropertyBase { }
class StringProperty : PropertyBase
{
public string Value { get; set; }
}
class ArrayProperty : PropertyBase
{
public IList<string> Value { get; set; }
}
class NumberProperty : PropertyBase
{
public double Value { get; set; }
}
class ExampleModel
{
public string NameProperty { get; set; }
public string OtherProperty
{
get; set;
}
public PropertyBase DifferentProperty { get; set; }
}
然后我想将对象列表传递给控制器功能的asp.net核心,例如:
public IActionResult ExampleFunction([FromBody] List<ExampleModel> request){ }
这是一个问题,因为我知道如何反序列化派生类的列表,但是我不知道如何反序列化具有抽象类型的属性的对象。我想编写一个JsonConvert类,该类将传递给asp.net mvc配置。
答案 0 :(得分:1)
我只是跳过了整个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();
}
}
为了知道哪个属性已解析,可以让ExampleModel包含DifferentPropertyEnum或其他属性,以便您知道解析中已填充了哪个属性。你明白了。
此外,请记住,在编译时将无法让您知道这实际上是什么样的属性。您无法使用 var 关键字或类似的关键字来访问它,因此,如果要经常使用该属性,则必须大量打开该属性。
您当然可以通过将DifferentProperty对象设置为动态对象(实际上是使用 dynamic 关键字)来绕过此操作。这不会生成编译器警告,但是如果您不小心就会使运行时崩溃。当然,它被认为更不安全,但是假设您的控制器只想将其存储在varchar数据库字段或其他内容中,那么我可能会选择动态的。
答案 1 :(得分:1)
您需要创建一个custom converter。
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);
}
}