2016-11-29 69 views
3

我在我的一个类中有一个属性,我试图用json.net序列化,我想“内联”,意思是说,我不用不想将属性嵌套到具有属性名称的元素中,但其内容直接位于其父元素中。如何使用json.net“嵌入”结果json中的属性

下面是一个例子,让我们说我有下面的类结构:

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 = "[email protected]"})}; 
    json = JsonConvert.SerializeObject(car2, Formatting.Indented); 
    Console.WriteLine(json); 
} 

你得到这样的结果:

{ 
    "CarBrand": "Ford", 
    "SteeringWheel": { 
    "TouchpadManufacturer": null, 
    "Identifier": { 
     "PartNumber": "123456" 
    } 
    } 
} 
{ 
    "CarBrand": "Toyota", 
    "SteeringWheel": { 
    "HornButtonManufacturer": null, 
    "Identifier": { 
     "ManufacturerEmail": "[email protected]" 
    } 
    } 
} 

但是,就我而言,标识符只是一种管理不同方式的方法,方向盘可以被识别出来,而且我不需要拥有那个属性。生成的JSON我期待会是以下几点:

{ 
    "CarBrand": "Ford", 
    "SteeringWheel": { 
    "TouchpadManufacturer": null 
    "PartNumber": "123456" 
    } 
} 
{ 
    "CarBrand": "Toyota", 
    "SteeringWheel": { 
    "HornButtonManufacturer": null, 
    "ManufacturerEmail": "[email protected]" 
    } 
} 

很显然,我可以通过在该ISteeringWheelManufacturerEmailPartNumber,并把一个或另一个null和设置忽略空值做到这一点,但我宁愿把事情正确地分开放在我的课堂上。

我创建了一个拨弄工作上面的代码在这里:https://dotnetfiddle.net/C9RPy9

谢谢!

回答

1

一种方法是为ISteeringWheelIdentifier创建您自己的自定义json解串器,其中您应该为每个方向盘标识符类型(请参阅http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm)实现所需的反序列化结果作为示例。然后你应该为你的Identifier属性设置一个JsonConverter属性[JsonConverter(typeof([New converter]的名称))],它将被反序列化,但是你指定了。

编辑 - 当实际执行它时,结果是获得所需行为有点技巧。您需要创建的转换器是用于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; } 
    } 
} 

现在剩下的工作就是将属性添加到汽车类:

public class Car 
{ 
    public string CarBrand { get; set; } 

    [JsonConverter(typeof(SteeringWheelJsonConverter))] 
    public ISteeringWheel SteeringWheel { get; set; } 

} 
+0

可否请你告诉我一个例子,因为我似乎并不能够改变使用JsonConverter属性的JSON的“左”部分。意思是,我仍然有“标识符”:“...” – Gimly

+0

看到我上面的编辑,它比我想象的更复杂:) – PartlyCloudy

+0

感谢您的帮助!这是非常烦人的,必须重新定义父的转换器,尤其是因为我的代码中的“ISteeringWheelIdentifier”的等价物实际上在几个类中使用,我必须以相同的方式重新定义它们(可能使用相同的方式代码,但仍然)。 – Gimly

相关问题