2015-04-30 9 views
6

Ho il seguente scenario: Sto utilizzando WebAPI e restituisco i risultati JSON al consumatore in base a un modello. Ora ho il requisito aggiuntivo di serializzare i modelli su base64 per poterli conservare in cache e/o usarli a fini di controllo. Il problema è che quando aggiungo l'attributo [Serializable] al modello modo per convertire il modello a Base64, i cambiamenti di uscita JSON come segue:Utilizzo dell'attributo serializzabile sul modello in WebAPI

Il Modello:

[Serializable] 
public class ResortModel 
{ 
    public int ResortKey { get; set; } 

    public string ResortName { get; set; } 
} 

Senza il [Serializable] attributo l'uscita JSON è :

{ 
    "ResortKey": 1, 
    "ResortName": "Resort A" 
} 

Con l'attributo [Serializable] l'uscita JSON è:

{ 
    "<ResortKey>k__BackingField": 1, 
    "<ResortName>k__BackingField": "Resort A" 
} 

Come potrei essere in grado di utilizzare l'attributo [Serializable] senza modificare l'output del JSON?

risposta

22

Per impostazione predefinita, Json.NET ignora l'attributo Serializable. Tuttavia, in base a un commento a this answer per Maggie Ying (riportato di seguito perché i commenti non sono destinati a durare), WebAPI sovrascrive tale comportamento, che causa l'output.

Il serializzatore Json.NET imposta per impostazione predefinita IgnoreSerializableAttribute su true. In WebAPI, lo impostiamo su false. Il motivo per cui si verifica questo problema è dovuto al fatto che Json.NET ignora le proprietà: "Json.NET ora rileva i tipi che hanno SerializableAttribute e serializza tutti i campi di quel tipo, sia pubblici che privati ​​e ignora le proprietà" (quotato da james.newtonking.com/archive/2012/04/11/…)

Un semplice esempio che dimostra lo stesso comportamento senza WebAPI può assomigliare a questo:

using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 
using System; 
namespace Scratch 
{ 
    [Serializable] 
    class Foo 
    { 
     public string Bar { get; set; } 
    } 

    class Program 
    { 
     static void Main() 
     { 
      var foo = new Foo() { Bar = "Blah" }; 
      Console.WriteLine(JsonConvert.SerializeObject(foo, new JsonSerializerSettings() 
       { 
        ContractResolver = new DefaultContractResolver() 
        { 
         IgnoreSerializableAttribute = false 
        } 
       })); 
     } 
    } 
} 

ci sono diversi modi per aggirare questo comportamento. Uno è quello di decorare il vostro modello con un attributo semplice JsonObject:

[Serializable] 
[JsonObject] 
class Foo 
{ 
    public string Bar { get; set; } 
} 

Un altro modo è quello di annullare le impostazioni predefinite nel Application_Start(). Secondo this answer, le impostazioni predefinite dovrebbero farlo:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings(); 

Se questo non dovesse funzionare, si potrebbe essere esplicito in proposito:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings() 
    { 
     ContractResolver = new DefaultContractResolver() 
     { 
      IgnoreSerializableAttribute = true 
     } 
    }; 
+0

Grazie Bart, grande risposta! Sono andato a usare 'GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();' in modo da non dover decorare ogni singolo modello con '[JsonObject]' – Ebbs