Создание десериализации свойств, но не сериализация с помощью 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?
  • Как я могу разбирать JSON с C #?
  • Отключить использование JSON.net
  • Web API 2: как вернуть JSON с именами свойств camelCased, на объекты и их под-объекты
  • Json.net сериализует определенное частное поле
  • Строка Parse Json в C #
  • Удаление десериализации полиморфных classов json без информации о типе с использованием json.net
  • JSON.net сериализуется непосредственно из oledbconnection
  • JSON.NET как сериализатор OAP для WebAPI 2 и ODataMediaTypeFormatter
  • Как я могу десериализовать JSON для простого словаря в ASP.NET?
  • Могу ли я сериализовать вложенные свойства в мой class за одну операцию с помощью Json.net?
  • Interesting Posts

    Установка переменных среды в OS X для приложений с графическим интерфейсом

    Выход NSTask в режиме реального времени в NSTextView с Swift

    Как настроить уведомление с помощью настраиваемого звука в android

    Сохранить изображение на SD-карте из ресурса на Android

    Как изменить значки меню навигации и переполнения панели инструментов (appcompat v7)?

    Проблемы, присущие jQuery $ .Deferred (jQuery 1.x / 2.x)

    Невозможно сделать статическую ссылку на нестатический метод

    Когда статический конструктор называется в C #?

    Событие изменения триггера автозаполнения jQuery

    Почему использование шестнадцатеричного в компьютере лучше, чем использование восьмеричного?

    В Java можно узнать, загружен ли class?

    Изменение цены при заказе при добавлении товара в корзину: magento

    Как добавить символ маркера в TextView?

    Странная проблема сравнения поплавков в объективе-C

    Как сделать ремонт Windows 10?

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