2012-04-16 41 views
139

tengo una clase DTO cual serializarCómo excluir la propiedad de la serialización JSON

Json.Serialize(MyClass) 

¿Cómo puedo excluir una propiedad pública de ella?

(tiene que ser público, como lo uso en mi código en otro lugar)

+4

marco que serialización se utilizan? –

+29

'IgnoreDataMember'' ScriptIgnore' 'JsonIgnore' dependiendo del serializador que use –

+1

también es digno de mención el atributo [NonSerialized], que solo se aplica a campos (no propiedades), pero tiene el mismo efecto que JsonIgnore. – Triynko

Respuesta

99

Puede poner un atributo ScriptIgnore en los miembros que no se deben serializar. Vea el ejemplo tomado de here:

Considere el caso siguiente (simplificado):

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

En este caso, sólo el ID y las propiedades Name serán serializados, por lo tanto el objeto JSON resultante se vería de esta manera:

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

PS. No olvide agregar una referencia a "System.Web.Extensions" para que funcione

+6

Encontré 'ScriptIgnore' en el espacio de nombres' System.Web.Script.Serialization' –

28

Puede utilizar [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); } 
    } 
} 

Referencia here

En este caso, la identificación y luego nombre solo será serializado

+0

La URL en su respuesta está rota. Es '[ScriptIgnore]' lo que debería usarse en la propiedad si su controlador está usando el controlador base MVC 'return Json (...'? – mmcrae

181

Si está utilizando Json.Net, el atributo [JsonIgnore] simplemente ignorará el campo/porperty durante la serialización o deserialización.

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

O puede usar el atributo DataContract y DataMember para serializar/deserializar selectivamente propiedades/campos.

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

Consulte http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size para más detalles

+26

Si fuera el OP, preferiría esta respuesta sobre la solución elegida [ScriptIgnore]. Principalmente debido a la congruencia de una solución Json por lo que un problema Json. ¿Por qué involucrar System.Web.Extensions cuando la biblioteca que está utilizando proporciona una solución? El mejor absoluto en mi humilde opinión es el atributo [IgnoreDataMember], como System.Runtime.La serialización debe ser compatible con cada serializador si desea cambiar Json. –

+0

'IgnoreDataMember' no funciona con el serializador' JsonResult' predeterminado. – Hendry

+0

NewtonSoft me ayudó por completo. Hizo que mi json se vea limpio sin que se incluyan propiedades desordenadas de mis modelos que son solo para back-end. –

8

Si no está tan interesado en tener que decorar código con atributos como yo, especialmente cuando usted no puede decir en tiempo de compilación lo que sucederá aquí está mi solución.

Utilizando el Javascript Serializador

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 cambio menor en la lógica y el 'PropertyExclusionConverter' se puede convertir en un' PropertyInclusionConverter'. – Zarepheth

+0

esto es simplemente increíble –

+0

Un posible problema con esto es que tiene que hacer el trabajo de coincidencia de nombres y exclusión una y otra vez cada vez que se serializa un objeto. Sin embargo, una vez compiladas, las propiedades de un tipo no cambiarán: debe precalcular, por tipo, los nombres que deben incluirse y solo reutilizar la lista en cada fila. Para un trabajo de serialización JSON muy masivo, el almacenamiento en caché podría hacer una diferencia notable en el rendimiento. – ErikE

Cuestiones relacionadas