277 votes

Comment exclure une propriété de la sérialisation Json ?

J'ai une classe DTO que je sérialise.

Json.Serialize(MyClass)

Comment puis-je exclure un public propriété de celui-ci ?

(Il doit être public, car je l'utilise dans mon code quelque part ailleurs)

7 votes

Quel cadre de sérialisation utilisez-vous ?

42 votes

IgnoreDataMember ScriptIgnore JsonIgnore en fonction du sérialiseur que vous utilisez

3 votes

Il convient également de noter l'attribut [NonSerialized], qui n'est applicable qu'aux champs (et non aux propriétés), mais qui a le même effet que JsonIgnore.

410voto

JC Raja Points 64

Si vous utilisez Json.Net attribut [JsonIgnore] ignorera simplement le champ/la propriété lors de la sérialisation ou de la désérialisation.

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

Vous pouvez également utiliser l'attribut DataContract et DataMember pour sérialiser/désérialiser les propriétés/champs de manière sélective.

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

Consultez le site http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size pour plus de détails

42 votes

Si j'étais le PO, je préférerais cette réponse à la solution choisie [ScriptIgnore]. Principalement en raison de la congruence entre une solution Json et un problème Json. Pourquoi impliquer System.Web.Extensions quand la bibliothèque que vous utilisez fournit une solution ? La meilleure solution, selon moi, est l'attribut [IgnoreDataMember], car System.Runtime.Serialization devrait être compatible avec tous les sérialiseurs si vous souhaitez remplacer Json.

0 votes

IgnoreDataMember ne fonctionne pas avec l'option par défaut JsonResult sérialiseur.

1 votes

NewtonSoft vient de m'aider pleinement. Il a fait en sorte que mon json soit propre sans que des propriétés désordonnées soient incluses dans mes modèles qui sont juste pour le backend.

157voto

Pavel Krymets Points 2556

Si vous utilisez System.Web.Script.Serialization dans le cadre de .NET vous pouvez mettre un ScriptIgnore sur les membres qui ne doivent pas être sérialisés. Voir l'exemple tiré de aquí :

Considérons le cas (simplifié) suivant :

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

Dans ce cas, seules les propriétés Id et Name seront sérialisées, et l'objet JSON résultant ressemblera à ceci :

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

PS. N'oubliez pas d'ajouter une référence à " System.Web.Extensions "pour que cela fonctionne

11 votes

J'ai trouvé ScriptIgnore en System.Web.Script.Serialization espace de noms.

0 votes

J'ai découvert que System.Web.Controller.Json() (c'est-à-dire renvoyer un JsonResult dans MVC) ne fonctionne qu'avec [ScriptIgnore], PAS avec [JsonIgnore]. Utilisez donc celle-ci pour les types JsonResult. Et oui, la référence correcte est System.Web.script.Serialization.

87voto

jitbit Points 8072

Désolé, j'ai décidé d'écrire une autre réponse puisqu'aucune des autres réponses n'est assez copiable.

Si vous ne voulez pas décorer les propriétés avec certains attributs, ou si vous n'avez pas accès à la classe, ou si vous voulez décider de ce qu'il faut sérialiser pendant l'exécution, etc. etc. voici comment vous faites dans Newtonsoft.Json

//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
    private readonly HashSet<string> ignoreProps;
    public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
    {
        this.ignoreProps = new HashSet<string>(propNamesToIgnore);
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (this.ignoreProps.Contains(property.PropertyName))
        {
            property.ShouldSerialize = _ => false;
        }
        return property;
    }
}

Utilisation

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

Note : assurez-vous que vous mettez en cache le ContractResolver si vous décidez d'utiliser cette réponse, sinon les performances peuvent en souffrir.

J'ai publié le code ici au cas où quelqu'un voudrait ajouter quelque chose.

https://github.com/jitbit/JsonIgnoreProps

33voto

Arion Points 17617

Vous pouvez utiliser [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); }
    }
}

Dans ce cas, l'Id et le nom seront seulement sérialisés

1 votes

L'URL dans votre réponse est cassé. Est-ce que [ScriptIgnore] ce qui devrait être utilisé sur la propriété si votre contrôleur utilise la base MVC Controller return Json(... ?

2 votes

Je sais que c'est un vieux commentaire, mais oui, utilisez [ScriptIgnore] dans le contrôleur MVC. Attention toutefois, si vous utilisez SignalR alors vous devez utiliser [JsonIgnore] aussi.

17voto

Si vous n'êtes pas aussi enthousiaste que moi à l'idée de devoir décorer le code avec des attributs, surtout lorsque vous ne pouvez pas savoir au moment de la compilation ce qui va se passer, voici ma solution.

Utilisation du sérialiseur 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
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X