Игнорировать свойство при сериализации с помощью Newtonsoft, но не при десериализации [duplicate]

Большинство приведенных выше ответов очищаются от нотации Slice. Расширенный синтаксис индексирования, используемый для нарезки, является aList[start:stop:step] базовыми примерами являются

:

Другие примеры нарезки: 15 Extended Slices

68
задан Will Dean 19 July 2012 в 16:25
поделиться

6 ответов

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

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

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<Config>(json);

// migrate
config.ReplacementSetting = 
    new Bang { Value = config.ObsoleteSetting.ToString() };

// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);

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

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

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

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

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

class Config
{
    public Fizz ObsoleteSetting { get; set; }

    public Bang ReplacementSetting { get; set; }

    public bool ShouldSerializeObsoleteSetting()
    {
        return false;
    }
}

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

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

Вместо использования JsonConvert.SerializeObject для выполнения сериализации загрузите config в 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 установщик свойств в класс с тем же типом, что и исходное свойство. Сделайте реализацию этого свойства, задайте исходное свойство.
  3. Примените атрибут [JsonProperty] к альтернативному сеттеру, присвоив ему то же имя JSON, что и исходное свойство.

Вот пересмотренный класс 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; }
}
78
ответ дан Brian Rogers 27 August 2018 в 00:30
поделиться

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

  • flag all ваш класс и подклассы в качестве «DataContract».
  • пометить все свойства вашего класса и подклассов как «DataMember».
  • flag все свойства вашего класса и подкатегории -classes как «JsonProperty», за исключением тех, которые вы хотите, чтобы они не были сериализованы.
  • теперь отмечают свойства, которые вы НЕ хотите, чтобы они сериализовались как «JsonIgnore».
  • затем Serialize используя «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<Meeting> Meetings { get; set; }
    
            public String toJSONString()
            {
                return JsonConvert.SerializeObject(this, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
            }
        }
    }
    

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

5
ответ дан Ahmed Abulazm 27 August 2018 в 00:30
поделиться

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

[JsonProperty(nameof(IgnoreOnSerializing))]
public string IgnoreOnSerializingSetter { set { IgnoreOnSerializing = value; } }

[JsonIgnore]
public string IgnoreOnSerializing;
6
ответ дан Bendik August Nesbø 27 August 2018 в 00:30
поделиться

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

public class JsonTest {

    public string SomeProperty { internal get; set; }

}

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

2
ответ дан Iucounu 27 August 2018 в 00:30
поделиться

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

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

public class JsonIgnoreSerializationAttribute : Attribute { }

ШАГ 2 - Создайте пользовательское соглашение об отказе

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

ШАГ 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<MyType>(myString);
19
ответ дан Jraco11 27 August 2018 в 00:30
поделиться

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

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

// 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<Guid> RefIds { get; set; }

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

1
ответ дан simo.37920 27 August 2018 в 00:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: