У нас есть несколько файлов конфигурации, которые были созданы путем сериализации объектов C # с помощью Json.net.
Мы хотели бы перенести одно свойство сериализованного класса из простого свойства перечисления в свойство класса.
Один из простых способов сделать это - оставить в классе старое свойство enum и организовать для Json.net чтение этого свойства при загрузке конфигурации, но не сохранение его снова при следующей сериализации объекта. Мы рассмотрим создание нового класса из старого перечисления отдельно.
Есть ли простой способ пометить (например, с помощью атрибутов) свойство объекта C #, чтобы Json.net игнорировал его ТОЛЬКО при сериализации, но обращал внимание на него при десериализации?
Ответы:
На самом деле существует несколько довольно простых подходов, которые можно использовать для достижения желаемого результата.
Предположим, например, что ваши классы в настоящее время определены следующим образом:
И вы хотите это сделать:
Чтобы получить это:
Подход 1. Добавьте метод ShouldSerialize
Json.NET имеет возможность условно сериализовать свойства путем поиска соответствующих
ShouldSerialize
методов в классе.Чтобы использовать эту функцию, добавьте
ShouldSerializeBlah()
в свой класс логический метод, которыйBlah
будет заменен именем свойства, которое вы не хотите сериализовать. Сделайте так, чтобы реализация этого метода всегда возвращаласьfalse
.Примечание: если вам нравится этот подход, но вы не хотите запутывать открытый интерфейс вашего класса, вводя
ShouldSerialize
метод, вы можете использовать,IContractResolver
чтобы сделать то же самое программно. См. Раздел « Сериализация условных свойств» в документации.Подход 2: манипулировать JSON с помощью JObjects
Вместо использования
JsonConvert.SerializeObject
для сериализации загрузите объект конфигурации в, аJObject
затем просто удалите нежелательное свойство из JSON перед его записью. Это всего лишь пара лишних строк кода.Подход 3: умное (ab) использование атрибутов
[JsonIgnore]
атрибут к свойству, которое не нужно сериализовать.[JsonProperty]
атрибут к альтернативному установщику, присвоив ему то же имя JSON, что и исходное свойство.Вот обновленный
Config
класс:источник
JsonPropertyAttribute
, начиная с C # 6.0, вы можете использоватьnameof
ключевое слово вместо использования «волшебных строк». Это делает рефакторинг намного проще и надежнее - плюс, если вы пропустите переименование каких-либо вхождений, компилятор все равно вас предупредит. Используя пример @Brian, можно использовать следующее:[JsonProperty(nameof(ObsoleteSetting))]
Для любой ситуации, когда допустимо, чтобы ваше свойство только для десериализации было помечено как внутреннее, существует удивительно простое решение, которое вообще не зависит от атрибутов. Просто отметьте свойство как внутреннее получение, но как открытый набор:
Это приводит к правильной десериализации с использованием параметров по умолчанию / преобразователей / и т. Д., Но свойство удаляется из сериализованного вывода.
источник
get
метода).internal
ниprivate
. Он всегда сериализуется.Мне нравится придерживаться атрибутов на этом, вот метод, который я использую, когда мне нужно десериализовать свойство, но не сериализовать его, или наоборот.
ШАГ 1. Создайте настраиваемый атрибут
ШАГ 2. Создайте настраиваемый повторный вывод контракта
ШАГ 3 - Добавьте атрибут, если сериализация не требуется, но десериализация
ШАГ 4 - Используйте это
Надеюсь это поможет! Также стоит отметить, что это также будет игнорировать свойства, когда происходит десериализация, когда я выполняю десериализацию, я просто использую конвертер обычным способом.
источник
GetSerializableMembers
а не полностью ее заменить?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Использовать свойство сеттера:
Надеюсь на эту помощь.
источник
IgnoreOnSerializing
, равные свойству. Я рекомендую использовать,nameof(IgnoreOnSerializing)
чтобы избежать волшебной строки, в случае переименования.После того, как я довольно долго искал, как пометить свойство класса как De-Serializable, а НЕ Serializable, я обнаружил, что этого вообще нет; поэтому я придумал решение, которое сочетает в себе две разные библиотеки или методы сериализации (System.Runtime.Serialization.Json и Newtonsoft.Json), и оно сработало для меня следующим образом:
затем выполните сериализацию с помощью «Newtonsoft.Json.JsonConvert.SerializeObject» и выполните десериализацию с помощью «System.Runtime.Serialization.Json.DataContractJsonSerializer».
Надеюсь, это поможет ...
источник
Что касается решения @ ThoHo, использование установщика - это на самом деле все, что нужно, без дополнительных тегов.
Для меня раньше у меня был единственный идентификатор ссылки, который я хотел загрузить и добавить в новую коллекцию идентификаторов ссылок. Изменяя определение идентификатора ссылки, чтобы он содержал только метод установки, который добавлял значение в новую коллекцию. Json не может записать значение обратно, если свойство не имеет значения get; метод.
Этот класс теперь обратно совместим с предыдущей версией и сохраняет только RefIds для новых версий.
источник
Чтобы основываться на ответе Тхо Хо, это также можно использовать для полей.
источник
В зависимости от того, где это происходит в приложении, и если это всего лишь одно свойство, вы можете сделать это вручную , установив значение свойства равным null, а затем в модели вы можете указать, что свойство игнорируется, если значение равно null:
Если вы работаете с веб-приложением ASP.NET Core, вы можете глобально установить это для всех свойств во всех моделях, установив это в своем файле Startup.cs:
источник
Если вы используете JsonConvert, IgnoreDataMemberAttribute в порядке. Моя стандартная библиотека не ссылается на Newton.Json, и я использую [IgnoreDataMember] для управления сериализацией объекта.
Из справочного документа Newton.net .
источник
На момент написания этой статьи я нашел самый простой способ - включить эту логику в ваш IContractResolver .
Пример кода из приведенной выше ссылки скопирован здесь для потомков:
Все ответы хороши, но этот подход казался самым чистым. На самом деле я реализовал это, ища атрибут в свойстве для SkipSerialize и SkipDeserialize, чтобы вы могли просто пометить любой контролируемый вами класс. Отличный вопрос!
источник