2013-02-28 19 views
6

Attualmente ho una classe che sembra qualcosa di simile:Come si personalizza la serializzazione JSON?

public class TestSerilizer 
{ 
    public int IntValue; 
    public DateTime DTValue; 
} 

e un controller che restituisce quella classe serializzato JSON che sembra qualcosa di simile:

public ActionResult TestJson() 
{ 
    TestSerilizer testDT = new TestSerilizer(); 
    return Json(testDT); 
} 

E 'ben noto che questo produce una data che assomiglia a qualcosa come /Date(123456)/ nel JSON che è meno desiderabile. Per i miei scopi mi piacerebbe poter aggiungere un attributo che formatta le mie date in un modo che abbia senso per il mio punto di vista. Idealmente mi piacerebbe cambiare il mio vista del modello di simile a questa:

public class TestSerilizer 
{ 
    public int IntValue; 
    [JSONDateFormatter("hh:mm tt")] 
    public DateTime DTValue; 
} 

che produrrebbe un insieme di dati JSON con la data formattata. C'è un modo per dirottare la serializzazione JSON per fare qualcosa del genere? Va notato che si tratta di una base di codice di grandi dimensioni che ha sia questa serializzazione JSON implicita sia l'uso esplicito della classe JavaScriptSerializer, quindi preferirei un metodo che funzioni per entrambe le situazioni, ma capisco che potrebbe non essere possibile.

+0

sono particolarmente tufo in JSON date. Di solito li tratta come stringhe e provo a inviarli in modo che javascript non tenti di interpretarli o gestirli –

risposta

7

Questo è in genere il modo in cui gestisco la serializzazione delle date per i miei oggetti. Si noti che questo utilizza DataMember proprietà perché ha bisogno di essere serializzabile sia da JSON binaria e:

[DataContract] 
[Serializable] 
public class YourClass 
{ 
     [DataMember] 
     private long timeStampLong; 


     [IgnoreDataMember] 
     public DateTime TimeStamp 
     { 
      get { return new DateTime(timeStampLong); } 
      set { timeStampLong = value.Ticks; } 
     } 
} 

Ora, questo non può fare il datetime come leggibile in JSON, ma sarà renderlo coerente. Diverse librerie json gestiscono la serializzazione di datetime in modo diverso, quindi si vuole essere in grado di forzare tutti a serializzare nello stesso modo.

Modifica: si noti che questa non è una seconda proprietà nel senso delle proprietà C# ma è solo il campo sottostante per la proprietà. Potresti rendere il campo sottostante una stringa, e quel campo sottostante non verrà mai esposto al di fuori dell'oggetto. A causa dello IgnoreDataMember, stai ancora serializzando un solo valore.

Edit2: aggiunta della dichiarazione di classe per una risposta più completa quando qualcuno deve implementarlo.

Edit: Per un esempio più completo ho pensato di includere l'altra opzione che ho usato (con una stringa come il campo supporto)

/// <summary> 
    /// Representations of the TimeStamp used for serialization 
    /// </summary> 
    [DataMember(Name = "TimeStamp")] 
    private String timeStamp; 

    /// <summary> 
    /// timestamp when the request is sent 
    /// </summary> 
    [IgnoreDataMember] 
    public DateTime TimeStamp 
    { 
     get { return DateTime.Parse(timeStamp, null, DateTimeStyles.RoundtripKind); } 
     set { timeStamp = value.ToUniversalTime().ToString("o"); } 
    } 
+0

questo è perfetto ... devo provare che –

+1

Abbiamo un sistema che ha bisogno di supportare più librerie json (come non so quale userà il nostro client), quindi in questo modo non importa se si utilizza il serializzatore .net, o newtonsoft, o qualche altro serializzatore json, verrà sempre serializzato solo il valore lungo. – jzworkman

+0

Speravo di non avere una seconda proprietà, ma sembra sempre più che non sarà possibile. – Mykroft

0

Come @jzworkman sottolineato, la tecnica di contorno in quella risposta è come controllare come viene serializzato il valore di DateTime interno. Continuo a usare sempre un formato basato su stringhe che può essere analizzato in modo affidabile da qualsiasi altra cosa. Se possibile, mi atteno all'utilizzo del formato ISO 8601 che può gestire correttamente la mappatura del fuso orario. In C#, è possibile utilizzare myDateTimeValue.ToString ("o") per ottenere la stringa per il DateTime nella norma ISO 8601.

Wikipedia article on ISO 8601

Problemi correlati