Настройте JSON.NET для игнорирования атрибутов DataContract / DataMember

Мы сталкиваемся с ситуацией в проекте MVC3 с сериализаторами Microsoft JSON и JSON.NET.

Всем известно, что DateTime в основном нарушены в сериализаторах Microsoft, поэтому мы перешли на JSON.NET, чтобы избежать этой проблемы. Это отлично работает, за исключением того, что некоторые из classов, которые мы пытаемся сериализовать, это POCOs с атрибутами DataContract / DataMember. Они определены в сборке, на которую ссылаются в разных местах. Кроме того, они имеют некоторые другие свойства отображения, которые не отмечены как данные для эффективности. Например, клиент

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

Когда этот клиент передается через WCF, клиентская сторона может ссылаться на эту сборку и использовать FullName просто отлично, но при сериализации с JSON.NET он видит, что FullName не является [DataMember] и не сериализует его. Есть ли возможность перейти на JSON.NET, чтобы сказать ему игнорировать тот факт, что class имеет атрибут [DataContract] ?

Примечание. Использование JavaScriptSerializer в .NET отлично подходит для свойства FullName, но DateTimes не работает. Мне нужен JSON.NET, чтобы игнорировать тот факт, что этот class имеет атрибуты DataContract / DataMember и просто выполняет стандартную сериализацию в публичном поле, как если бы они не были там.

Просто используйте атрибут OptOut от Json.Net. Он будет иметь приоритет над DataContract.

 [DataContract] [JsonObject(MemberSerialization.OptOut)] 

Как сказал Амри, вы можете использовать свой собственный 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; } } 

Есть несколько строк, прокомментированных, они не требуют, чтобы мое решение работало, но вы никогда не знаете!

Это имеет то же значение, что и решение Amry:

 var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings { ContractResolver = new AllPropertiesResolver() }); 

Надеюсь это поможет!

У меня была проблема, почти связанная с тем, что у вас есть, и удалось найти решение, пройдя коды Json.NET. Так что это может быть не лучшее решение, но оно работает для меня.

Для этого вам необходимо реализовать свой собственный IContractResolver . Более упрощенная реализация этого для включения всех параметров и игнорирует все атрибуты (не только DataContract но и другие встроенные правила Json.NET, поэтому любые параметры, которые вы устанавливаете, которые должны первоначально влиять на выбор участников, теперь перекрываются этим кодом ):

 class AllPropertiesResolver : DefaultContractResolver { protected override List GetSerializableMembers(Type objectType) { return objectType.GetProperties() .Where(p => p.GetIndexParameters().Length == 0) .Cast() .ToList(); } } 

И вот пример использования кода:

 var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings { ContractResolver = new AllPropertiesResolver() }); 

Если вы хотите игнорировать присутствие 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()).FirstOrDefault(a => a != null); var jsonObjectAttribute = type.GetCustomAttribute(); if (dataContractAttribute != null && jsonObjectAttribute == null) memberSerialization = MemberSerialization.OptOut; } return memberSerialization; } protected override IList 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 BaseTypesAndSelf(this Type type) { while (type != null) { yield return type; type = type.BaseType; } } } 

Вы можете захотеть кэшировать распознаватель контракта для достижения наилучшей производительности .

В соответствии с документацией Json.NET [DataMember] атрибуты игнорируются, если свойства также аннотируются с конкретными атрибутами Json.NET (такими как [JsonProperty] ). Подробнее см. Документацию по атрибутам Serialization Attributes :

Атрибуты Json.NET берут на себя ответственность за стандартные атрибуты сериализации .NET, например, если оба свойства JsonPropertyAttribute и DataMemberAttribute присутствуют в свойстве и оба настраивают имя, будет использоваться имя из JsonPropertyAttribute.

Документация охватывает только свойство name, но по моему опыту [JsonProperty] также полностью [JsonProperty] настройки, выполняемые [DataMember] . Итак, если это возможно для вашего случая, также добавьте атрибуты Json.NET в свойства, для которых аннотацию [DataMember] следует игнорировать.

Вы пробовали это?

IgnoreDataMemberAttribute

  • Как игнорировать неизвестные значения enum во время десериализации json?
  • Настройка пользовательских дат WebApi Json.NET
  • Как написать Json-файл в C #?
  • Удалить дескриптор объекта json в динамический объект с помощью Json.net
  • Серийный объект Json.NET с корневым именем
  • Уничтожить вложенные JSON в объекты C #
  • Разбор JSON DateTime от JSON Serializer от Newtonsoft
  • Невозможно десериализовать текущий объект JSON (например, {"name": "value"}) в тип 'System.Collections.Generic.List`1
  • Как игнорировать свойство в classе, если null, используя json.net
  • Как я могу разобрать строку JSON, которая приведет к незаконным идентификаторам C #?
  • Как сериализовать словарь как часть его родительского объекта с помощью Json.Net
  • Давайте будем гением компьютера.