web-dev-qa-db-fra.com

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 une propriété publique?

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

206
Elad Benda

Si vous utilisez System.Web.Script.Serialization dans le framework .NET , vous pouvez définir un attribut ScriptIgnore . sur les membres qui ne devraient pas être sérialisés. Voir l'exemple pris de ici :

Considérons le cas suivant (simplifié):

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. 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.

134
Pavel Krymets

Si vous utilisez Json.Net , l'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 les attributs DataContract et DataMember pour sérialiser/désérialiser sélectivement les propriétés/champs.

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

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

311
JC Raja

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

Référence ici

Dans ce cas, l'identifiant puis le nom ne seront sérialisés

30
Arion

Si vous ne souhaitez pas décorer le code avec les attributs comme je le suis, surtout si vous ne pouvez pas dire au moment de la compilation ce qui va arriver, voici ma solution.

Utiliser le 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
        }
    }
13
Thulani Chivandikwa