2012-04-16 11 views
139

Ho una classe DTO che ho serializzareCome escludere immobili da serializzazione JSON

Json.Serialize(MyClass) 

Come posso escludere una proprietà pubblica di esso?

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

+4

quadro che serializzazione si usa? –

+29

'IgnoreDataMember'' ScriptIgnore' 'JsonIgnore' a seconda del serializzatore utilizzato –

+1

anche l'attributo [NonSerialized], che è applicabile solo ai campi (non proprietà), ma ha lo stesso effetto di JsonIgnore. L'URL – Triynko

risposta

99

È possibile inserire un attributo ScriptIgnore sui membri che non deve essere serializzato. Vedere l'esempio tratto da here:

Si consideri 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 l'ID e le proprietà del nome verranno serializzati, in tal modo l'oggetto JSON risultante apparirebbe in questo modo:

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

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

+6

Ho trovato 'ScriptIgnore' nel namespace' System.Web.Script.Serialization'. –

28

È possibile utilizzare [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 here

In questo caso l'ID e poi il nome verrà serializzato solo

+0

nella risposta è rotto. È '[ScriptIgnore]' cosa dovrebbe essere usato sulla proprietà se il controller sta usando il controller di base MVC 'return Json (...'? – mmcrae

181

Se si utilizza Json.Net, l'attributo [JsonIgnore] semplicemente ignorerà il campo/la porzionatura 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 è possibile utilizzare l'attributo DataContract e DataMember per serializzare in modo selettivo/deserializzare 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; } 
} 

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

+26

Se fossi l'OP, preferirei questa risposta rispetto alla soluzione [ScriptIgnore] scelta, principalmente a causa della congruenza di una soluzione Json, quindi un problema Json. Perché coinvolgere System.Web.Extensions quando la libreria che stai utilizzando fornisce una soluzione? Il migliore IMHO assoluto è l'attributo [IgnoreDataMember], come System.Runtime.La serializzazione dovrebbe essere compatibile con tutti i serializzatori se si desidera sostituire Json. –

+0

'IgnoreDataMember' non funziona con il serializzatore predefinito' JsonResult'. – Hendry

+0

NewtonSoft mi ha appena aiutato completamente. Ha reso il mio json un aspetto pulito, senza le proprietà disordinate incluse nei miei modelli che sono solo per il back-end. –

8

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

Usando il Javascript Serializzatore

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

Una piccola modifica nella logica e 'PropertyExclusionConverter' può essere trasformata in un' PropertyInclusionConverter'. – Zarepheth

+0

questo è semplicemente fantastico –

+0

Un potenziale problema con questo è che deve fare il lavoro di abbinamento e di esclusione del nome più e più volte ogni volta che un oggetto viene serializzato. Tuttavia, una volta compilate, le proprietà di un tipo non cambieranno: dovresti fare questo pre-calcolare, per tipo, i nomi che dovrebbero essere inclusi e riutilizzare solo l'elenco su ogni riga. Per un lavoro di serializzazione JSON molto massiccio, il caching potrebbe fare una notevole differenza nelle prestazioni. – ErikE

Problemi correlati