我在我的一个类中有一个属性,我正在尝试使用json.net进行序列化,我想“内联”,这意味着,我不希望将属性嵌套到具有属性名称的元素中,但其内容直接在其母公司内.
这是一个例子,假设我有以下类结构:
public interface ISteeringWheelIdentifier {}
public interface ISteeringWheel
{
ISteeringWheelIdentifier Identifier {get;}
}
public class ManufacturerIdentifier : ISteeringWheelIdentifier
{
public string ManufacturerEmail {get; set;}
}
public class PartNumberIdentifier : ISteeringWheelIdentifier
{
public string PartNumber {get; set;}
}
public class ClassicSteeringWheel : ISteeringWheel
{
public ClassicSteeringWheel(ManufacturerIdentifier identifier)
{
Identifier = identifier;
}
public string HornButtonManufacturer {get; set;}
public ISteeringWheelIdentifier Identifier {get;private set;}
}
public class ModernSteeringWheel : ISteeringWheel
{
public ModernSteeringWheel(PartNumberIdentifier identifier)
{
Identifier = identifier;
}
public string TouchpadManufacturer {get; set;}
public ISteeringWheelIdentifier Identifier {get;private set;}
}
public class Car
{
public string CarBrand {get; set;}
public ISteeringWheel SteeringWheel {get; set;}
}
如果我尝试使用以下代码序列化两个测试对象:
public static void Main()
{
var car1 = new Car{CarBrand="Ford", SteeringWheel = new ModernSteeringWheel(new PartNumberIdentifier{PartNumber = "123456"})};
var json = JsonConvert.SerializeObject(car1, Formatting.Indented);
Console.WriteLine(json);
var car2 = new Car{CarBrand="Toyota", SteeringWheel = new ClassicSteeringWheel(new ManufacturerIdentifier{ManufacturerEmail = "test@demo.com"})};
json = JsonConvert.SerializeObject(car2, Formatting.Indented);
Console.WriteLine(json);
}
你得到这个结果:
{
"CarBrand": "Ford",
"SteeringWheel": {
"TouchpadManufacturer": null,
"Identifier": {
"PartNumber": "123456"
}
}
}
{
"CarBrand": "Toyota",
"SteeringWheel": {
"HornButtonManufacturer": null,
"Identifier": {
"ManufacturerEmail": "test@demo.com"
}
}
}
但是,对于我的情况,标识符只是一种管理方向盘识别方式的方法,我不需要拥有该属性.由此产生的Json我期待如下:
{
"CarBrand": "Ford",
"SteeringWheel": {
"TouchpadManufacturer": null
"PartNumber": "123456"
}
}
{
"CarBrand": "Toyota",
"SteeringWheel": {
"HornButtonManufacturer": null,
"ManufacturerEmail": "test@demo.com"
}
}
显然,我可以通过在ISteeringWheel中同时使用ManufacturerEmail和PartNumber并将一个或另一个null设置为忽略空值来实现,但我宁愿在我的类中正确分隔事物.
我在这里用上面的代码创建了一个小提琴:https://dotnetfiddle.net/C9RPy9
最佳答案 一种方法是为ISteeringWheelIdentifier创建自己的自定义json反序列化器,在其中您应该为每个方向盘标识符类型实现所需的反序列化结果(请参阅
http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm)以获取示例.然后你应该为你的Identifier属性设置一个JsonConverter属性[JsonConverter(typeof([你的新转换器的名称]))]然后你会指定它反序列化.
编辑 – 当实际实现它时,结果是有点琐碎以获得所需的行为.您需要创建的转换器是ISteeringWheel接口的转换器.在其中,遍历所有属性,直到获得标识符属性,并处理其序列化.举个例子:
public class SteeringWheelJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(ISteeringWheel).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jo = new JObject();
Type type = value.GetType();
foreach (var prop in type.GetProperties())
{
if (prop.CanRead)
{
var propVal = prop.GetValue(value, null);
if (prop.Name == "Identifier")
{
// Iterate over all properties of the identifier, but don't add the identifier object itself
// to the serialized result.
Type identifierType = propVal.GetType();
foreach (var identifierProp in identifierType.GetProperties())
{
var identifierPropVal = identifierProp.GetValue(propVal, null);
jo.Add(identifierProp.Name, identifierPropVal != null ? JToken.FromObject(identifierPropVal, serializer) : null);
}
}
else
{
// Add the property to the serialized result
jo.Add(prop.Name, propVal != null ? JToken.FromObject(propVal, serializer) : null);
}
}
}
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanRead
{
get { return false; }
}
}
现在剩下的就是将属性添加到car类:
public class Car
{
public string CarBrand { get; set; }
[JsonConverter(typeof(SteeringWheelJsonConverter))]
public ISteeringWheel SteeringWheel { get; set; }
}