Come escludere la proprietà dalla serializzazione Json


235

Ho una classe DTO che serializzo

Json.Serialize(MyClass)

Come posso escluderne una proprietà pubblica ?

(Deve essere pubblico, come lo uso nel mio codice da qualche altra parte)


4
Quale framework di serializzazione usi?
Pavel Gatilov,

37
IgnoreDataMember ScriptIgnore JsonIgnorea seconda del serializzatore che usi
LB

3
degno di nota è anche l'attributo [Non serializzato], che è applicabile solo ai campi (non alle proprietà), ma per il resto ha lo stesso effetto di JsonIgnore.
Triynko,

Il commento di Trynko è molto utile .... se usi IgnoreDataMember su un campo non ci saranno errori, ma non verrà applicato.
Tillito,

Risposte:


147

Se si utilizza System.Web.Script.Serializationin .NET framework è possibile inserire un ScriptIgnoreattributo sui membri che non dovrebbe essere serializzato. Vedi l'esempio preso da qui :

Considera il seguente caso (semplificato):

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

In questo caso, solo le proprietà Id e Name verranno serializzate, quindi l'oggetto JSON risultante sarà simile al seguente:

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

PS. Non dimenticare di aggiungere un riferimento a " System.Web.Extensions" affinché funzioni


10
Ho trovato ScriptIgnorenello System.Web.Script.Serializationspazio dei nomi.
Sorangwala Abbasali,

354

Se si utilizza l' attributo Json.Net[JsonIgnore] semplicemente ignorerà il campo / proprietà durante la serializzazione o la deserializzazione.

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

Oppure puoi usare l'attributo DataContract e DataMember per serializzare / deserializzare selettivamente proprietà / campi.

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

Fare riferimento a http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size per maggiori dettagli


37
Se fossi il PO, preferirei questa risposta rispetto alla soluzione scelta [ScriptIgnore]. Principalmente a causa della congruenza di una soluzione Json, quindi un problema Json. Perché coinvolgere System.Web.Extensions quando la libreria in uso fornisce una soluzione? L'IMHO migliore in assoluto è l'attributo [IgnoreDataMember], poiché System.Runtime.Serialization dovrebbe essere compatibile con ogni serializzatore se si desidera scambiare Json.
Steve H.

IgnoreDataMembernon funziona con il JsonResultserializzatore predefinito .
hendryanw,

1
NewtonSoft mi ha aiutato completamente. Ha reso il mio JSON pulito, senza alcuna proprietà disordinata inclusa nei miei modelli che sono solo per il backend.
Sorangwala Abbasali,

1
@JC Raja Come posso ignorare la proprietà durante la desalinizzazione solo quando questa proprietà è nulla
user123456

1
[NewtonSoft.Json] Voglio ignorare solo la serializzazione. Quindi una soluzione per questo?
Trương Quốc Khánh,

31

Puoi usare [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); }
    }
}

Riferimento qui

In questo caso, l'ID e il nome verranno serializzati


1
L'URL nella tua risposta è rotto. È [ScriptIgnore]quello che dovrebbe essere utilizzato sulla proprietà se il controller utilizza la MVC base Controller return Json(...?
Don Cheadle

2
So che è un vecchio commento, ma sì, utilizzare [ScriptIgnore]nel controller MVC. Attenzione, se si utilizza SignalR , è necessario utilizzare [JsonIgnore]anche.
Sam,

22

Mi dispiace, ho deciso di scrivere un'altra risposta poiché nessuna delle altre risposte è abbastanza incollabile.

Se non vuoi decorare le proprietà con alcuni attributi, o se non hai accesso alla classe, o se vuoi decidere cosa serializzare durante il runtime, ecc. Ecc. Ecco come lo fai in 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;
    }
}

uso

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

Ho pubblicato il codice qui nel caso qualcuno volesse aggiungere qualcosa

https://github.com/jitbit/JsonIgnoreProps

AGGIORNAMENTO IMPORTANTE: assicurati di memorizzare nella cache l' ContractResolveroggetto se decidi di utilizzare questa risposta, altrimenti le prestazioni potrebbero risentirne.


15

Se non sei così appassionato di dover decorare il codice con Attributi come lo sono io, specialmente quando non puoi dire al momento della compilazione cosa accadrà qui è la mia soluzione.

Utilizzando il serializzatore 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
Un piccolo cambiamento nella logica e PropertyExclusionConverterpuò essere trasformato in a PropertyInclusionConverter.
Zarepheth,

è semplicemente fantastico
SaiKiran Mandhala il

Un potenziale problema con questo è che deve fare il lavoro di abbinamento dei nomi e di esclusione ogni volta che un oggetto viene serializzato. Tuttavia, una volta compilato, le proprietà di un tipo non cambieranno - dovresti fare questo pre-calcolo, per tipo, dei nomi da includere e riutilizzare semplicemente l'elenco su ogni riga. Per un lavoro di serializzazione JSON molto massiccio, la memorizzazione nella cache potrebbe fare una notevole differenza nelle prestazioni.
ErikE,

9

Se stai usando, System.Text.Jsonallora puoi usare [JsonIgnore].
FQ:System.Text.Json.Serialization.JsonIgnoreAttribute

Documenti Microsoft ufficiali: JsonIgnoreAttribute

Come indicato qui :

La libreria è integrata come parte del framework condiviso .NET Core 3.0.
Per altri framework di destinazione, installare il pacchetto NuGet System.Text.Json. Il pacchetto supporta:

  • .NET Standard 2.0 e versioni successive
  • .NET Framework 4.6.1 e versioni successive
  • .NET Core 2.0, 2.1 e 2.2

0

Puoi anche usare l' [NonSerialized]attributo

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

Dai documenti MS :

Indica che un campo di una classe serializzabile non deve essere serializzato. Questa classe non può essere ereditata.


Se stai usando Unity per esempio ( questo non è solo per Unity ), allora funzionaUnityEngine.JsonUtility

using UnityEngine;

MySerializableStruct mss = new MySerializableStruct 
{ 
    hiddenField = "foo", 
    normalField = "bar" 
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.