2015-09-04 20 views
2

當使用XSD.EXE生成從XML架構的類時,它產生一個給定的對象的任何原語的xxxSpecified成員:XSD.EXE + JSON.NET - 如何處理xxxSpecified生成的成員?

<xs:complexType name ="Foo"> 
    <xs:all> 
     <xs:element name ="Count" type = "xs:integer"/> 
    </xs:all> 
</xs:complexType> 

....生成:

public class Foo 
{ 
    public int Count { get; set; } 
    public bool CountSpecified { get; set; } 
} 

它出現在最新版本的JSON.NET可以在反序列化時自動設置這些屬性。

string request = "{ Count : 10 }"; 
var object = JsonConvert.Deserialize<Foo>(request) 
Assert.IsTrue(object.Count = 10); // Yup 
Assert.IsTrue(object.CountSpecified == true); //Also yup - JSON.NET works! 

然而,去其他方式的情況下,xxxSpecified特性被包括在JSON輸出,這是不正確的,因爲它不是架構的一部分。

string request = JsonConvert.Serialize(object); 
//{ 
// Count: 10, 
// CountSpecified : true <-- This is incorrect - should not be output 
//} 

是否有我缺少的設置控制是否輸出xxxSpecified屬性?我怎樣才能壓制它?

(注:這是一個問題的回答排列這裏:

JSON.NET, XmlSerializer and "Specified" property

...但它涉及到創建擴展類,這是不可能對我來說,因爲有幾百個班架構,我無法改變繼承層次所以答案是行不通尋找另一種方式)

回答

2

您可以創建自己的合同,解析過濾掉xxxSpecified屬性:。

public class SkipSpecifiedContractResolver : DefaultContractResolver 
{ 
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. 
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm 
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm 
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." 
    static SkipSpecifiedContractResolver instance; 

    static SkipSpecifiedContractResolver() { instance = new SkipSpecifiedContractResolver(); } 

    public static SkipSpecifiedContractResolver Instance { get { return instance; } } 

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     var properties = base.CreateProperties(type, memberSerialization); 
     ILookup<string, JsonProperty> lookup = null; 
     foreach (var property in properties) 
     { 
      if (property.GetIsSpecified != null && property.SetIsSpecified != null) 
      { 
       var name = property.UnderlyingName + "Specified"; 
       lookup = lookup ?? properties.ToLookup(p => p.UnderlyingName); 
       var specified = lookup[name].SingleOrDefault(); 
       if (specified != null) 
        specified.Ignored = true; 
      } 
     } 
     return properties; 
    } 
} 

然後使用它像:

 var settings = new JsonSerializerSettings { ContractResolver = SkipSpecifiedContractResolver.Instance }; 
     var object = JsonConvert.DeserializeObject<Foo>(request, settings); 

如果你想永遠這樣做,你可以設置合同解析器在全球JsonConvert.DefaultSettings

 JsonConvert.DefaultSettings = (() => 
     { 
      return new JsonSerializerSettings { ContractResolver = SkipSpecifiedContractResolver.Instance }; 
     }); 
+1

輝煌的答案。像魅力一樣工作。謝謝! –