Jak wykluczyć właściwość z serializacji Json


234

Mam klasę DTO, którą szereguję

Json.Serialize(MyClass)

Jak mogę wykluczyć jego własność publiczną ?

(Musi być publiczny, ponieważ używam go w kodzie gdzie indziej)


4
Z jakich ram serializacji korzystasz?
— Pavel Gatilov

37
IgnoreDataMember ScriptIgnore JsonIgnorew zależności od używanego serializatora
— LB

3
na uwagę zasługuje również atrybut [NonSerialized], który ma zastosowanie tylko do pól (nie właściwości), ale poza tym ma taki sam efekt jak JsonIgnore.
— Triynko

Komentarz Trynko jest bardzo przydatny .... jeśli użyjesz IgnoreDataMember na polu, nie będzie błędu, ale nie zostanie zastosowany.
— Tillito,

Odpowiedzi:


147

Jeśli używasz System.Web.Script.Serializationw środowisku .NET , możesz nadać ScriptIgnoreczłonkom atrybut, którego nie należy szeregować. Zobacz przykład wzięty stąd :

Rozważ następujący (uproszczony) przypadek:

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

W takim przypadku tylko właściwości Id i Nazwa zostaną przekształcone do postaci szeregowej, dlatego wynikowy obiekt JSON będzie wyglądał następująco:

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

PS. Nie zapomnij dodać odniesienia do „ System.Web.Extensions”, aby to zadziałało


10
Znalazłem ScriptIgnorew System.Web.Script.Serializationprzestrzeni nazw.
— Sorangwala Abbasali

354

Jeśli używasz atrybutu Json.Net[JsonIgnore] , po prostu zignorujesz pole / właściwość podczas serializacji lub deserializacji.

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; }
}

Lub możesz użyć atrybutu DataContract i DataMember do selektywnej serializacji / deserializacji właściwości / pól.

[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; }
}

Patrz http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size więcej szczegółów


37
Gdybym był OP, wolałbym tę odpowiedź niż wybrane rozwiązanie [ScriptIgnore]. Przede wszystkim ze względu na zgodność rozwiązania Json z problemem Json. Po co angażować System.Web.Extensions, gdy używana biblioteka zapewnia rozwiązanie? Absolutnie najlepszym IMHO jest atrybut [IgnoreDataMember], ponieważ System.Runtime.Serialization powinien być kompatybilny z każdym serializatorem, jeśli chcesz zamienić Jsona.
— Steve H.

IgnoreDataMembernie działa z domyślnym JsonResultserializatorem.
— hendryanw,

1
NewtonSoft pomógł mi w pełni. To sprawiło, że mój json wyglądał czysto, bez żadnych nieporządnych właściwości z moich modeli, które są tylko dla backendu.
— Sorangwala Abbasali

1
@JC Raja Jak mogę zignorować właściwość podczas odsalania tylko wtedy, gdy ta właściwość jest pusta
— 24.04.17

1
[NewtonSoft.Json] Chcę zignorować tylko serializację. Jakieś rozwiązanie tego problemu?
— Trương Quốc Khánh

31

Możesz użyć [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); }
    }
}

Odnośnik tutaj

W takim przypadku identyfikator, a następnie nazwa będą tylko serializowane


1
Adres URL w odpowiedzi jest uszkodzony. Czy [ScriptIgnore]należy korzystać z właściwości, jeśli kontroler korzysta z podstawowego kontrolera MVC return Json(...?
— Don Cheadle

2
Wiem, że to stary komentarz, ale tak, użyj [ScriptIgnore]w MVC Controller. Pamiętaj jednak, że jeśli używasz SignalR , powinieneś [JsonIgnore]również użyć .
— Sam

21

Przepraszamy, postanowiłem napisać inną odpowiedź, ponieważ żadnej z pozostałych odpowiedzi nie można wystarczająco wkleić.

Jeśli nie chcesz dekorować właściwości za pomocą niektórych atrybutów lub jeśli nie masz dostępu do klasy, lub jeśli chcesz zdecydować, co do serializacji w czasie wykonywania itp. Itp., Oto jak to zrobić w 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;
    }
}

Stosowanie

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

Opublikowałem tutaj kod na wypadek, gdyby ktoś chciał coś dodać

https://github.com/jitbit/JsonIgnoreProps

WAŻNA AKTUALIZACJA: upewnij się, że buforujesz ContractResolverobiekt, jeśli zdecydujesz się użyć tej odpowiedzi, w przeciwnym razie może to pogorszyć wydajność.


15

Jeśli nie lubisz dekorować kodu atrybutami tak, jak ja, szczególnie gdy nie możesz powiedzieć w czasie kompilacji, co się tutaj stanie, to moje rozwiązanie.

Korzystanie z Serializatora 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
Niewielka zmiana w logice i PropertyExclusionConvertermoże być przekształcona w PropertyInclusionConverter.
— Zarepheth,

to jest po prostu niesamowite
— SaiKiran Mandhala,

Jednym z potencjalnych problemów jest to, że musi on ciągle dopasowywać nazwy i wykluczać za każdym razem, gdy obiekt jest szeregowany. Jednak po skompilowaniu właściwości typu nie zmienią się - należy wstępnie obliczyć dla każdego typu nazwy, które należy uwzględnić, i po prostu ponownie użyć listy w każdym wierszu. W przypadku bardzo masowego zadania serializacji JSON buforowanie może mieć zauważalną różnicę w wydajności.
— ErikE

9

Jeśli używasz System.Text.Json, możesz użyć [JsonIgnore].
FQ:System.Text.Json.Serialization.JsonIgnoreAttribute

Oficjalne dokumenty Microsoft: JsonIgnoreAttribute

Jak stwierdzono tutaj :

Biblioteka jest wbudowana jako część wspólnego środowiska .NET Core 3.0.
W przypadku innych platform docelowych zainstaluj pakiet System.Text.Json NuGet. Pakiet obsługuje:

  • .NET Standard 2.0 i nowsze wersje
  • .NET Framework 4.6.1 i nowsze wersje
  • .NET Core 2.0, 2.1 i 2.2

0

Możesz także użyć [NonSerialized]atrybutu

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

Z dokumentów MS :

Wskazuje, że pole klasy możliwej do serializacji nie powinno być serializowane. Ta klasa nie może być dziedziczona.


Jeśli używasz na przykład Unity ( nie dotyczy to tylko Unity ), to działa zUnityEngine.JsonUtility

using UnityEngine;

MySerializableStruct mss = new MySerializableStruct 
{ 
    hiddenField = "foo", 
    normalField = "bar" 
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.