2012-12-10 12 views
8

Quando si utilizza JSON.Net per serializzare/deserializzare le strutture, un tipo di struttura build-in (come System.Drawing.Size) viene serializzato su una stringa, mentre un tipo di struct personalizzato si serializza su un oggetto JSON.JSON.Net Struct Serialization Discrepancy

Ad esempio:

using System; 
using System.Drawing; 
using Newtonsoft.Json; 

namespace TestJsonNet 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(JsonConvert.SerializeObject(new Size(50, 50))); 
      Console.WriteLine(JsonConvert.SerializeObject(new Size2(50, 50))); 
     } 
    } 

    struct Size2 
    { 
     public int Width { get; set; } 
     public int Height { get; set; } 
     public Size2(int w, int h) : this() 
     { 
      Width = w; Height = h; 
     } 
    } 
} 

Uscite quanto segue:

"50, 50" 
{"Width":50,"Height":50} 

posso capire la filosofia che ispira la serializzazione una struct in una stringa, dal momento che il layout di memoria è sempre lo stesso; tuttavia, perché la discrepanza durante la serializzazione di una struttura personalizzata?

Inoltre, vorrei (per motivi di legacy interna), come avere JSON.Net serializzare le strutture come quest'ultimo caso (cioè come JSON, non stringa). Se è possibile, come può essere raggiunto?

+1

Ho trovato questo articolo [JSON.NET serializzazione guai] (http://stackoverflow.com/questions/9750836/json-net-serialization-trouble) , tuttavia mi piacerebbe comunque disattivare questo comportamento per tutti i tipi di struct in un colpo solo. –

risposta

2

Utilizzando la riflessione è possibile risolvere questo problema. Ho preso parte alla soluzione da te suggerita e ho utilizzato la reflection per ottenere i nomi e i valori delle proprietà.

class StructConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var myObject = (object)value; 
     var jObject = new JObject(); 

     Type myType = myObject.GetType(); 
     IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties()); 

     foreach (PropertyInfo prop in props) 
     { 

      jObject.Add(prop.Name, prop.GetValue(myObject, null).ToString()); 
     } 
     serializer.Serialize(
      writer, jObject); 
    } 

....

public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsValueType; 
    } 
} 
+0

La vera risposta alla mia domanda è: non puoi. Non c'è modo di configurare JSON.NET in modo che usi il proprio convertitore invece del TypeConverter. Ma ti darò il check (e il badge del negromante?) Visto che probabilmente è il più generico. –

+0

Grazie Dave. Mi chiedo se ci sono serializzatori JSON per .net là fuori che lo fanno fuori dalla scatola. –

+0

Sì, ci sono. Dai un'occhiata a ServiceStack.Text. Se fornisci due funzioni Parse e ToString a una struttura, prende quelle per deserializzare e serializzare. Lo trovo abbastanza utile. – jruizaranguren