下面分几个类。如何序列化 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;}
}
我看到了这个问题的多种解决方案,但它们缺乏优雅:
- 将属性的类型作为对象:我失去了该属性的强类型。
- 将有问题的部分重新序列化为子对象:这很快就会变得丑陋
- 创建一个特定的类ASerialisable(具有B1和B2属性),将字符串序列化为此,然后使用构造函数从该类创建一个A对象:与上面相同,我担心如果有的话它会创建很多类类似的问题还有很多。
*在序列化之前添加对象的类型并使用属性TypeNameHandling。我没有看到一种不涉及部分反序列化的方法。
类似的问题,但我也不是序列化字符串的人,所以我无法使用此解决方案:反序列化为正确的子对象 https://stackoverflow.com/questions/22465868/deserialize-into-correct-child-objects
EDIT:
我创建了一个继承 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; }
}
如果这种情况仅在少数情况下出现,请序列化为具有这两个属性的 DTO(数据传输对象)类。如果您不想创建新的命名类,您还可以使用匿名类来为您完成这项工作
var myDto = JsonConvert.DeserializeAnonymousType(jsonString,
new {
PropertyB = new {
GenProp ="",
SpecPropB1 ="",
SpecPropB2 = ""}
});
如果这种情况出现得太频繁,也就是说,如果您不确定要反序列化的 json 的架构,则可以反序列化为 JObject,然后查询字段是否存在。
B b;
JObject o = JObject.Parse(jsonString);
// I need this variable to compile, but I won't use it.
JToken _;
if(o.TryGetValue("SpecPropB1", out _)
{
b = o.ToObject<B1>();
}
else
{
//...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)