如何处理xxxSpecified生成的成员

如何处理xxxSpecified生成的成员

本文介绍了XSD.EXE + JSON.NET-如何处理xxxSpecified生成的成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用XSD.EXE从XML架构生成类时,它会生成给定对象的任何原语的xxxSpecified成员:

When using XSD.EXE to generate classes from an XML Schema, it generates xxxSpecified members of any primitives of a given object:

<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可以自动设置这些属性.

It appears the latest version of JSON.NET can automatically set these properties when deserializing.

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输出中,这是不正确的,因为它不是架构的一部分.

However, when going the other way, the xxxSpecified properties are included in the JSON output, which is incorrect, as it is not part of the schema.

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

我是否缺少用于控制是否输出xxxSpecified属性的任何设置?我该如何抑制呢?

Is there any setting I am missing that controls whether to output the xxxSpecified attributes? How can I suppress it?

(注意:这是对此处回答的问题的排列:

(Note: This is a permutation of a question answered here:

JSON.NET,XmlSerializer和"Specified"财产

...但是它涉及创建扩展类,这对我来说是不可能的,因为架构中有数百个类,而且我无法更改继承层次结构.因此,答案将无济于事.寻找另一种方式.)

...but it involves creating extension classes, which is not possible for me, as there are hundreds of classes in the schema and I can't change the inheritance hierarchy. So the answer won't work. Looking for another way.)

推荐答案

您可以创建自己的合同解析器来过滤xxxSpecified属性:

You can create your own contract resolver to filter out xxxSpecified properties:

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]
                    // Possibly also check for [XmlIgnore] being applied.  While not shown in the question, xsd.exe will always
                    // apply [XmlIgnore] to xxxSpecified tracking properties.
                    //.Where(p => p.AttributeProvider.GetAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute),true).Any())
                    .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 :

If you want to do this always, you can set the contract resolver in the global JsonConvert.DefaultSettings:

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

这篇关于XSD.EXE + JSON.NET-如何处理xxxSpecified生成的成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 08:05