Як виключити властивість з Json Serialization


234

У мене клас DTO, який я серіалізую

Json.Serialize(MyClass)

Як я можу виключити публічну власність цього?

(Це повинно бути загальнодоступним, оскільки я використовую його у своєму коді де-небудь ще)


4
Яку рамку серіалізації ви використовуєте?
Павло Гатилов

37
IgnoreDataMember ScriptIgnore JsonIgnoreзалежно від використовуваного серіалізатора
LB

3
також заслуговує на увагу атрибут [NonSerialized], який застосовний лише до полів (не властивостей), але в іншому випадку має такий же ефект, як JsonIgnore.
Трайнко

Коментар Trynko дуже корисний .... якщо ви використовуєте IgnoreDataMember у полі, помилок не буде, але він не застосовуватиметься.
Тілліто

Відповіді:


147

Якщо ви використовуєте System.Web.Script.Serializationв .NET рамках, ви можете розмістити ScriptIgnoreатрибут членів, які не повинні бути серіалізовані. Дивіться приклад, взятий звідси :

Розглянемо наступний (спрощений) випадок:

public class User {
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    } 
} 

У цьому випадку серіалізуватимуться лише властивості Id та Name, таким чином отриманий об'єкт JSON виглядатиме так:

{ Id: 3, Name: 'Test User' }

PS. Не забудьте додати посилання на " System.Web.Extensions", щоб це працювало


10
Я знайшов ScriptIgnoreу System.Web.Script.Serializationпросторі імен.
Sorangwala Abbasali

354

Якщо ви використовуєте атрибут Json.Net,[JsonIgnore] він просто ігнорує поле / властивість під час серіалізації або десеріалізації.

public class Car
{
  // included in JSON
  public string Model { get; set; }
  public DateTime Year { get; set; }
  public List<string> Features { get; set; }

  // ignored
  [JsonIgnore]
  public DateTime LastModified { get; set; }
}

Або ви можете використовувати атрибут DataContract і DataMember для вибіркової серіалізації / деріаріалізації властивостей / полів.

[DataContract]
public class Computer
{
  // included in JSON
  [DataMember]
  public string Name { get; set; }
  [DataMember]
  public decimal SalePrice { get; set; }

  // ignored
  public string Manufacture { get; set; }
  public int StockCount { get; set; }
  public decimal WholeSalePrice { get; set; }
  public DateTime NextShipmentDate { get; set; }
}

Для отримання детальної інформації див. Http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size


37
Якби я був ОП, я віддав би перевагу цій відповіді над обраним рішенням [ScriptIgnore]. В першу чергу через конгруентність рішення Джсона, тому проблема Json. Навіщо включати System.Web.Extensions, коли бібліотека, яку ви використовуєте, пропонує рішення? Абсолютним найкращим IMHO є атрибут [IgnoreDataMember], оскільки System.Runtime.Serialization має бути сумісним з кожним серіалізатором, якщо ви бажаєте замінити Json.
Стів Х.

IgnoreDataMemberне працює з JsonResultсеріалізатором за замовчуванням .
hendryanw

1
NewtonSoft просто мені повністю допоміг. Це зробило мій json чистим без будь-яких брудних властивостей, включених із моїх моделей, які призначені лише для бекенда.
Sorangwala Abbasali

1
@JC Raja Як я можу ігнорувати майно під час знезараження лише тоді, коли ця властивість є нульовою
user123456

1
[NewtonSoft.Json] Я хочу ігнорувати лише серіалізацію. Тоді якесь рішення для цього?
Trương Quốc Khánh

31

Ви можете використовувати [ScriptIgnore]:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    }
}

Довідка тут

У цьому випадку Id і тоді ім'я будуть лише серіалізовані


1
URL-адреса у вашій відповіді порушена. Є чи [ScriptIgnore]то , що має бути використано на майно , якщо ваш контролер використовує базу MVC контролер return Json(...?
Don Cheadle

2
Я знаю, що це старий коментар, але так, використовуйте [ScriptIgnore]в MVC Controller. Але будьте попереджені, якщо ви використовуєте SignalR , тоді вам слід також скористатися [JsonIgnore].
Сем

21

Вибачте, що я вирішив написати ще одну відповідь, оскільки жодна з інших відповідей не є достатньо копіювальною.

Якщо ви не хочете прикрашати властивості деякими атрибутами, або у вас немає доступу до класу, або якщо ви хочете вирішити, що серіалізувати під час виконання, і т. Д. Тощо, ось як це зробити в Newtonsoft.Json

//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
    private IEnumerable<string> _propsToIgnore;
    public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
    {
        _propsToIgnore = propNamesToIgnore;
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        property.ShouldSerialize = (x) => { return !_propsToIgnore.Contains(property.PropertyName); };
        return property;
    }
}

Використання

JsonConvert.SerializeObject(YourObject, new JsonSerializerSettings()
    { ContractResolver = new IgnorePropertiesResolver(new[] { "Prop1", "Prop2" }) };);

Я опублікував тут код на випадок, якщо хтось хоче щось додати

https://github.com/jitbit/JsonIgnoreProps

ВАЖЛИВО ОНОВЛЕННЯ: переконайтесь, що ви кешуєте ContractResolverоб’єкт, якщо ви вирішили використовувати цю відповідь, інакше може постраждати продуктивність.


15

Якщо ви не так зацікавлені в тому, щоб прикрашати код атрибутами, як я, особливо, коли ви не можете сказати під час компіляції, що буде тут, це моє рішення.

Використання серіалізатора Javascript

    public static class JsonSerializerExtensions
    {
        public static string ToJsonString(this object target,bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            if(ignoreNulls)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(target.GetType(), true) });
            }
            return javaScriptSerializer.Serialize(target);
        }

        public static string ToJsonString(this object target, Dictionary<Type, List<string>> ignore, bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            foreach (var key in ignore.Keys)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(key, ignore[key], ignoreNulls) });
            }
            return javaScriptSerializer.Serialize(target);
        }
    }


public class PropertyExclusionConverter : JavaScriptConverter
    {
        private readonly List<string> propertiesToIgnore;
        private readonly Type type;
        private readonly bool ignoreNulls;

        public PropertyExclusionConverter(Type type, List<string> propertiesToIgnore, bool ignoreNulls)
        {
            this.ignoreNulls = ignoreNulls;
            this.type = type;
            this.propertiesToIgnore = propertiesToIgnore ?? new List<string>();
        }

        public PropertyExclusionConverter(Type type, bool ignoreNulls)
            : this(type, null, ignoreNulls){}

        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { this.type })); }
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary<string, object>();
            if (obj == null)
            {
                return result;
            }
            var properties = obj.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {
                if (!this.propertiesToIgnore.Contains(propertyInfo.Name))
                {
                    if(this.ignoreNulls && propertyInfo.GetValue(obj, null) == null)
                    {
                         continue;
                    }
                    result.Add(propertyInfo.Name, propertyInfo.GetValue(obj, null));
                }
            }
            return result;
        }

        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException(); //Converter is currently only used for ignoring properties on serialization
        }
    }

1
Незначна зміна логіки та кані PropertyExclusionConverterможе перетворитись на a PropertyInclusionConverter.
Зареф

це просто приголомшливо
SaiKiran Mandhala

Однією з можливих проблем цього є те, що він повинен виконувати роботу зі збіганням імен та виключенням кожного разу при кожному серіалізації об'єкта. Однак після компіляції властивості типу не змінюватимуться - слід попередньо обчислити, за типом, імена, які слід включити, та просто використати список у кожному рядку. Для дуже масштабної роботи з серіалізації JSON кешування може помітно змінити продуктивність.
ЕрікЕ

9

Якщо ви використовуєте, System.Text.Jsonто ви можете використовувати [JsonIgnore].
FQ:System.Text.Json.Serialization.JsonIgnoreAttribute

Офіційні документи Microsoft: JsonIgnoreAttribute

Як зазначено тут :

Бібліотека вбудована як частина загальної структури .NET Core 3.0.
Для інших цільових рамок встановіть пакет System.Text.Json NuGet. Пакет підтримує:

  • .NET Standard 2.0 та новіших версій
  • .NET Framework 4.6.1 та новіших версій
  • .NET Core 2.0, 2.1 та 2.2

0

Ви також можете використовувати [NonSerialized]атрибут

[Serializable]
public struct MySerializableStruct
{
    [NonSerialized]
    public string hiddenField;
    public string normalField;
}

З документів MS :

Вказує, що поле класу, що серіалізується, не повинно бути серіалізованим. Цей клас не може бути успадкований.


Якщо ви, наприклад, використовуєте Unity ( це не тільки для Unity ), це працюєUnityEngine.JsonUtility

using UnityEngine;

MySerializableStruct mss = new MySerializableStruct 
{ 
    hiddenField = "foo", 
    normalField = "bar" 
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.