配置JSON.NET以忽略DataContract/DataMember属性

Nic*_*ick 35 c# json datacontract datamember json.net

我们在使用Microsoft JSON序列化程序和JSON.NET的MVC3项目中遇到了这种情况.

每个人都知道DateTime在Microsoft的序列化程序中基本上被打破了,所以我们切换到JSON.NET来避免这个问题.这很好用,除了我们尝试序列化的一些类是具有DataContract/DataMember属性的POCO.它们在多个位置引用的程序集中定义.此外,它们还具有一些其他显示属性,这些属性未标记为DataMembers以提高效率.例如,客户

[DataContract]
public class Customer
{
   [DataMember]
   public string FirstName { get; set;}
   [DataMember]
   public string LastName { get; set;}
   public string FullName 
   {
       get
       {  return FirstName + " " + LastName; }
   }

}
Run Code Online (Sandbox Code Playgroud)

当这个客户通过WCF传递时,客户端可以引用该程序集并使用FullName就好了,但是当使用JSON.NET序列化时,它会看到FullName不是a [DataMember]并且不会序列化它.是否可以选择传递给JSON.NET,告诉它忽略类已[DataContract]应用属性的事实?

注意: 在.NET中使用JavaScriptSerializer可以很好地处理FullName属性,但DateTimes会被破坏.我需要JSON.NET忽略这个类具有DataContract/DataMember属性的事实,并且只是执行标准的公共字段序列化,就像它们不在那里一样.

sel*_*ary 28

只需使用Json.Net的OptOut属性即可.它将优先于DataContract.

[DataContract]
[JsonObject(MemberSerialization.OptOut)]
Run Code Online (Sandbox Code Playgroud)


小智 18

正如Amry所说,你可以使用自己的IContractResolver.

不幸的是,Amry提供的解决方案对我不起作用,下面是我设法开始工作的解决方案:

public class AllPropertiesResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        //property.HasMemberAttribute = true;
        property.Ignored = false;

        //property.ShouldSerialize = instance =>
        //{
        //    return true;
        //};

        return property;
    }
}
Run Code Online (Sandbox Code Playgroud)

有几行评论,这些不需要让我的解决方案工作,但你永远不知道!

这与Amry的解决方案具有相同的用法:

var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
    ContractResolver = new AllPropertiesResolver()
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


Amr*_*mry 14

我遇到了与您所拥有的问题几乎相关的问题,并通过查看Json.NET的代码找到了解决方案.所以它可能不是最好的解决方案,但它对我有用.

要做到这一点,您需要实现自己的IContractResolver.过度简化的实现包括所有参数并忽略所有属性(不仅仅是DataContract其他内置的Json.NET规则,因此您设置的最初应影响成员选择的任何选项现在都被此代码覆盖) :

class AllPropertiesResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        return objectType.GetProperties()
            .Where(p => p.GetIndexParameters().Length == 0)
            .Cast<MemberInfo>()
            .ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里是代码用法示例:

var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
    ContractResolver = new AllPropertiesResolver()
});
Run Code Online (Sandbox Code Playgroud)

  • 大.为什么不?什么不起作用?帮助我们帮助您. (2认同)

ren*_*ene 8

根据Json.NET文档,[DataMember]如果属性也使用Json.NET特定属性(例如[JsonProperty])注释,则忽略属性.有关详细信息,请参阅序列化属性文档:

Json.NET属性主要使用标准.NET序列化属性,例如,如果属性上存在JsonPropertyAttribute和DataMemberAttribute,并且都自定义名称,则将使用JsonPropertyAttribute中的名称.

该文档仅涵盖name属性,但根据我的经验,该[JsonProperty]属性还完全影响属性所做的设置[DataMember].因此,如果它适用于您的情况,还要将Json.NET属性添加到应忽略[DataMember]注释的属性.

  • 从您的回答中,我了解到,如果一个类具有 **[DataContract]** 属性,那么它将成员序列化设置为 **选择加入**,这意味着任何成员(_field 或 property_)**必须**要序列化的 JsonProperty 或 **[DataMember]** 属性(_否则它将被忽略_)。我花了几个小时才找到这些信息。 (2认同)

dbc*_*dbc 7

如果要忽略DataContractAttribute所有类型的存在而不必添加其他属性,则自定义合同解析程序是正确的解决方案.但是,从Json.NET 9.0.1开始,Amry的解析器不再有效. Doolali的解析器有效,但它具有序列化所有公共属性的额外副作用,包括标记的那些[JsonIgnore].如果您需要合同解析程序,只能忽略其存在DataContractAttribute但行为类似于默认合同解析程序,则可以使用以下内容:

public class IgnoreDataContractContractResolver : DefaultContractResolver
{
    static MemberSerialization RemoveDataContractAttributeMemberSerialization(Type type, MemberSerialization memberSerialization)
    {
        if (memberSerialization == MemberSerialization.OptIn)
        {
            type = Nullable.GetUnderlyingType(type) ?? type;

            // Json.NET interprets DataContractAttribute as inherited despite the fact it is marked with Inherited = false
            // https://json.codeplex.com/discussions/357850
            // https://stackoverflow.com/questions/8555089/datacontract-and-inheritance
            // https://github.com/JamesNK/Newtonsoft.Json/issues/603
            // Thus we need to manually climb the type hierarchy to see if one is present.

            var dataContractAttribute = type.BaseTypesAndSelf().Select(t => t.GetCustomAttribute<DataContractAttribute>()).FirstOrDefault(a => a != null);
            var jsonObjectAttribute = type.GetCustomAttribute<JsonObjectAttribute>();

            if (dataContractAttribute != null && jsonObjectAttribute == null)
                memberSerialization = MemberSerialization.OptOut;
        }
        return memberSerialization;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, RemoveDataContractAttributeMemberSerialization(type, memberSerialization));
        return properties;
    }

    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);
        contract.MemberSerialization = RemoveDataContractAttributeMemberSerialization(objectType, contract.MemberSerialization);
        return contract;
    }
}

public static class TypeExtensions
{
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望缓存合同解析程序以获得最佳性能.


duc*_*kus -3

你试过这个吗?

忽略数据成员属性

  • 我想做与忽略该字段相反的事情,我希望在使用 JSON.NET 序列化时包含该字段 (2认同)