Создание десериализации свойств, но не сериализация с помощью json.net

У нас есть некоторые файлы конфигурации, которые были сгенерированы путем сериализации объектов C # с помощью Json.net.

Мы хотим перенести одно свойство сериализованного classа из простого свойства enum в свойство classа.

Одним из простых способов сделать это было бы оставить прежнее свойство enum в classе и организовать Json.net для чтения этого свойства, когда мы загружаем конфигурацию, но не сохраняем его снова, когда следующий сериализуем объект. Мы будем заниматься созданием нового classа из старого enums отдельно.

Есть ли простой способ отметить (например, с атрибутами) свойство объекта C #, чтобы Json.net игнорировал его ТОЛЬКО при сериализации, но рассматривал его при десериализации?

На самом деле существует несколько довольно простых подходов, которые вы можете использовать для достижения желаемого результата.

Предположим, например, что у вас в настоящее время определены ваши classы следующим образом:

class Config { public Fizz ObsoleteSetting { get; set; } public Bang ReplacementSetting { get; set; } } enum Fizz { Alpha, Beta, Gamma } class Bang { public string Value { get; set; } } 

И вы хотите сделать это:

 string json = @"{ ""ObsoleteSetting"" : ""Gamma"" }"; // deserialize Config config = JsonConvert.DeserializeObject(json); // migrate config.ReplacementSetting = new Bang { Value = config.ObsoleteSetting.ToString() }; // serialize json = JsonConvert.SerializeObject(config); Console.WriteLine(json); 

Чтобы получить это:

 {"ReplacementSetting":{"Value":"Gamma"}} 

Подход 1: Добавить метод ShouldSerialize

Json.NET имеет возможность условно сериализовать свойства, ища соответствующие методы ShouldSerialize в classе.

Чтобы использовать эту функцию, добавьте логический метод ShouldSerializeBlah() в ваш class, где Blah заменяется именем свойства, которое вы не хотите сериализовать. Сделать реализацию этого метода всегда возвращает false .

 class Config { public Fizz ObsoleteSetting { get; set; } public Bang ReplacementSetting { get; set; } public bool ShouldSerializeObsoleteSetting() { return false; } } 

Примечание. Если вам нравится этот подход, но вы не хотите испортить публичный интерфейс своего classа, введя метод ShouldSerialize , вы можете использовать IContractResolver для IContractResolver чтобы делать то же самое программно. См. Раздел « Сериализация условных свойств» в документации.

Подход 2: Управление JSON с помощью JObjects

Вместо использования JsonConvert.SerializeObject для сериализации загрузите объект конфигурации в JObject , а затем просто удалите нежелательное свойство из JSON перед его записью. Это всего лишь пара дополнительных строк кода.

 JObject jo = JObject.FromObject(config); // remove the "ObsoleteSetting" JProperty from its parent jo["ObsoleteSetting"].Parent.Remove(); json = jo.ToString(); 

Подход 3: Умный (ab) использование атрибутов

  1. Примените [JsonIgnore] к свойству, которое вы не хотите сериализовать.
  2. Добавьте альтернативный, private property setter в class с тем же типом, что и исходное свойство. Сделайте реализацию этого свойства, задав исходное свойство.
  3. Примените [JsonProperty] к альтернативному сетевому устройству, присвоив ему то же имя JSON, что и исходное свойство.

Вот отредактированный class Config :

 class Config { [JsonIgnore] public Fizz ObsoleteSetting { get; set; } [JsonProperty("ObsoleteSetting")] private Fizz ObsoleteSettingAlternateSetter { // get is intentionally omitted here set { ObsoleteSetting = value; } } public Bang ReplacementSetting { get; set; } } 

Мне нравится придерживаться атрибутов на этом, вот метод, который я использую, когда вам нужно десериализовать свойство, но не сериализуйте его или наоборот.

ШАГ 1 – Создайте пользовательский атрибут

 public class JsonIgnoreSerializationAttribute : Attribute { } 

ШАГ 2 – Создайте индивидуальный заказчик Reslover

 class JsonPropertiesResolver : DefaultContractResolver { protected override List GetSerializableMembers(Type objectType) { //Return properties that do NOT have the JsonIgnoreSerializationAttribute return objectType.GetProperties() .Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))) .ToList(); } } 

ШАГ 3 – Добавить атрибут, в котором сериализация не требуется, но десериализация

  [JsonIgnoreSerialization] public string Prop1 { get; set; } //Will be skipped when serialized [JsonIgnoreSerialization] public string Prop2 { get; set; } //Also will be skipped when serialized public string Prop3 { get; set; } //Will not be skipped when serialized 

ШАГ 4 – Используйте его

 var sweet = JsonConvert.SerializeObject(myObj, new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }); 

Надеюсь это поможет! Также стоит отметить, что это также игнорирует свойства, когда происходит Deserialization, когда я занимаюсь сортировкой, я просто использую конвертер обычным способом.

 JsonConvert.DeserializeObject(myString); 

Использовать свойство setter:

 [JsonProperty(nameof(IgnoreOnSerializing))] public string IgnoreOnSerializingSetter { set { _ignoreOnSerializing = value; } } [JsonIgnore] private string _ignoreOnSerializing; [JsonIgnore] public string IgnoreOnSerializing { get { return this._ignoreOnSerializing; } set { this._ignoreOnSerializing = value; } } 

Надеюсь, эта помощь.

После того, как я потратил довольно много времени на поиск того, как помечать свойство classа De-Serializable и NOT Serializable, я обнаружил, что этого не существует вообще; поэтому я придумал решение, которое объединяет две разные библиотеки или методы сериализации (System.Runtime.Serialization.Json & Newtonsoft.Json), и это сработало для меня следующим образом:

  • отметьте все ваши classы и подclassы как «DataContract».
  • пометить все свойства вашего classа и подclassов как «DataMember».
  • пометить все свойства вашего classа и подclassов как «JsonProperty», кроме тех, которые вы хотите, чтобы они не были сериализованы.
  • теперь отметьте свойства, которые вы НЕ хотите, чтобы они были сериализованы как «JsonIgnore».
  • затем Сериализовать с помощью «Newtonsoft.Json.JsonConvert.SerializeObject» и De-Serialize с помощью «System.Runtime.Serialization.Json.DataContractJsonSerializer».

     using System; using System.Collections.Generic; using Newtonsoft.Json; using System.Runtime.Serialization; using System.IO; using System.Runtime.Serialization.Json; using System.Text; namespace LUM_Win.model { [DataContract] public class User { public User() { } public User(String JSONObject) { MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(JSONObject)); DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(User)); User user = (User)dataContractJsonSerializer.ReadObject(stream); this.ID = user.ID; this.Country = user.Country; this.FirstName = user.FirstName; this.LastName = user.LastName; this.Nickname = user.Nickname; this.PhoneNumber = user.PhoneNumber; this.DisplayPicture = user.DisplayPicture; this.IsRegistred = user.IsRegistred; this.IsConfirmed = user.IsConfirmed; this.VerificationCode = user.VerificationCode; this.Meetings = user.Meetings; } [DataMember(Name = "_id")] [JsonProperty(PropertyName = "_id")] public String ID { get; set; } [DataMember(Name = "country")] [JsonProperty(PropertyName = "country")] public String Country { get; set; } [DataMember(Name = "firstname")] [JsonProperty(PropertyName = "firstname")] public String FirstName { get; set; } [DataMember(Name = "lastname")] [JsonProperty(PropertyName = "lastname")] public String LastName { get; set; } [DataMember(Name = "nickname")] [JsonProperty(PropertyName = "nickname")] public String Nickname { get; set; } [DataMember(Name = "number")] [JsonProperty(PropertyName = "number")] public String PhoneNumber { get; set; } [DataMember(Name = "thumbnail")] [JsonProperty(PropertyName = "thumbnail")] public String DisplayPicture { get; set; } [DataMember(Name = "registered")] [JsonProperty(PropertyName = "registered")] public bool IsRegistred { get; set; } [DataMember(Name = "confirmed")] [JsonProperty(PropertyName = "confirmed")] public bool IsConfirmed { get; set; } [JsonIgnore] [DataMember(Name = "verification_code")] public String VerificationCode { get; set; } [JsonIgnore] [DataMember(Name = "meeting_ids")] public List Meetings { get; set; } public String toJSONString() { return JsonConvert.SerializeObject(this, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }); } } } 

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

В любой ситуации, когда допустимо, чтобы свойство десериализации было отмечено внутренним, существует удивительно простое решение, которое вообще не зависит от атрибутов. Просто отметьте свойство как внутренний get, но общеansible набор:

 public class JsonTest { public string SomeProperty { internal get; set; } } 

Это приводит к правильной десериализации с использованием настроек по умолчанию / resolvers / etc., Но свойство удаляется из сериализованного вывода.

со ссылкой на решение @ ThoHo, использование setter – это на самом деле все, что необходимо, без дополнительных тегов.

Для меня у меня ранее был единственный идентификатор ссылки, который я хотел загрузить и добавить в новую коллекцию ссылочных идентификаторов. Изменив определение ссылочного идентификатора, будет только содержать метод setter, который добавит значение в новую коллекцию. Json не может записать значение обратно, если свойство не имеет get; метод.

 // Old property that I want to read from Json, but never write again. No getter. public Guid RefId { set { RefIds.Add(value); } } // New property that will be in use from now on. Both setter and getter. public ICollection RefIds { get; set; } 

Этот class теперь обратно совместим с предыдущей версией и сохраняет только RefIds для новых версий.

Чтобы основываться на ответе Тхо Хо, это также можно использовать для полей.

 [JsonProperty(nameof(IgnoreOnSerializing))] public string IgnoreOnSerializingSetter { set { IgnoreOnSerializing = value; } } [JsonIgnore] public string IgnoreOnSerializing; 
  • Уничтожить вложенные JSON в объекты C #
  • Установка стандартного JSON-сериализатора в ASP.NET MVC
  • Разбор массива JSON с использованием Json.Net
  • Сериализовать словарь как массив (пар ключей)
  • JSON.net: как десериализовать без использования конструктора по умолчанию?
  • В чем разница между PreserveReferencesHandling и ReferenceLoopHandling в Json.Net?
  • JSON.NET: зачем использовать JToken - когда-либо?
  • Json.NET (Newtonsoft.Json) - Два «свойства» с таким же именем?
  • Deserialize json с известными и неизвестными полями
  • Как сообщить Json.Net глобально применить StringEnumConverter ко всем enumsм
  • Конвенция о присвоении имен JSON
  • Interesting Posts

    Запись команды вывода в Windows cmd в файл (с завихрением)

    C ++ singleton против глобального статического объекта

    Создание gradleиентов программным путем?

    WCF: настройка известных типов

    Как запретить вход в систему для удаленного рабочего стола, когда пользователь регистрируется локально?

    Пример сокета клиента Python

    Как создавать платы судоку с уникальными решениями

    Как загрузить файл в браузер из хранилища Azure Blob

    NSMutableArray addObject: – : непризнанный селектор, отправленный экземпляру

    Программно введите секретный код, например * # * # 4636 # * # * на Android

    Android получает текущую локаль, а не по умолчанию

    Как я могу сохранить работу своего Android-сервиса, когда экран выключен?

    GCC фатальная ошибка: stdio.h: нет такого файла или каталога

    Как создать пользовательский элемент редактора PropertyGrid, который открывает форму?

    Может ли getDerivedStateFromProps использоваться в качестве альтернативы componentWillReceiveProps

    Давайте будем гением компьютера.