2012-02-07 18 views
7

Ho bisogno di serializzare oggetti su JSON. Mi piacerebbe farlo con un modello invece di utilizzare le annotazioni di dati (come la maggior parte dei framework). Qualcuno conosce un buon modo per farlo?Serializzazione temporizzata degli oggetti C# su JSON

Un'immagine dice più di 1000 parole. Sto cercando qualcosa che assomiglia a questo:

enter image description here

Per esempio, se ho avuto una classe come questa:

public class Test 
{ 
    public string Key { get; set; } 
    public string Name { get; set; } 
    public string Code { get; set; } 
    public Test Related { get; set; } 
} 

E una stringa di modello avuto quel potrebbe assomigliare a questo :

{ 
    id: "$Key", 
    name: "$Name", 
    related: "$Related.Name" 
} 

voglio ottenere un oggetto JSON, le cui proprietà sono compilati in base al Key, Name e Related.Name dell'oggetto.

Fondamentalmente io sto alla ricerca di un metodo diserializzazione JSON che supporta template invece.

+0

Non è molto chiaro cosa esattamente vuoi. Vuoi creare un metodo che ha quel modello hard-coded e funziona su qualsiasi tipo che ha 'Key',' Name' e 'Related.Name'? O vuoi un sistema completo in grado di capire i modelli nel formato che hai specificato e serializzare usando questi? – svick

+0

@ KeesC.Bakker Nessuno è richiesto per spiegare i downvotes, poiché il downvoting è anonimo. Inoltre, questa domanda non mostra alcuno sforzo di ricerca ed è incredibilmente vaga (e si può sostenere che non è costruttiva, visto che in sostanza stai chiedendo un elenco di prodotti/articoli). – casperOne

+1

@casperOne, non sono d'accordo sul fatto che questa domanda non sia costruttiva. Si chiede come fare una cosa specifica. Penso che si possa ragionevolmente rispondere in un modo che si adatti a SO, almeno nella forma attuale. (Ho modificato il campione del template e ho provato a spiegarlo di più.) – svick

risposta

4

Non so di qualsiasi libreria che fa per voi, ma non è così difficile da costruire da soli.

Se si dispone del modello, è necessario analizzarlo come JSON e quindi sostituire tutti i segnaposto con valori effettivi. Per fare ciò, puoi usare il modello visitatore.

Dal JSON.NET (la libreria JSON che sto usando) non sembrano avere un visitatore, è possibile creare uno voi stessi:

abstract class JsonVisitor 
{ 
    public virtual JToken Visit(JToken token) 
    { 
     var clone = token.DeepClone(); 
     return VisitInternal(clone); 
    } 

    protected virtual JToken VisitInternal(JToken token) 
    { 
     switch (token.Type) 
     { 
     case JTokenType.Object: 
      return VisitObject((JObject)token); 
     case JTokenType.Property: 
      return VisitProperty((JProperty)token); 
     case JTokenType.Array: 
      return VisitArray((JArray)token); 
     case JTokenType.String: 
     case JTokenType.Integer: 
     case JTokenType.Float: 
     case JTokenType.Date: 
     case JTokenType.Boolean: 
     case JTokenType.Null: 
      return VisitValue((JValue)token); 
     default: 
      throw new InvalidOperationException(); 
     } 
    } 

    protected virtual JToken VisitObject(JObject obj) 
    { 
     foreach (var property in obj.Properties()) 
      VisitInternal(property); 

     return obj; 
    } 

    protected virtual JToken VisitProperty(JProperty property) 
    { 
     VisitInternal(property.Value); 

     return property; 
    } 

    protected virtual JToken VisitArray(JArray array) 
    { 
     foreach (var item in array) 
      VisitInternal(item); 

     return array; 
    } 

    protected virtual JToken VisitValue(JValue value) 
    { 
     return value; 
    } 
} 

e quindi creare un visitatore specializzato che sostituisce i segnaposto con valori effettivi:

class JsonTemplateVisitor : JsonVisitor 
{ 
    private readonly object m_data; 

    private JsonTemplateVisitor(object data) 
    { 
     m_data = data; 
    } 

    public static JToken Serialize(object data, string templateString) 
    { 
     return Serialize(
      data, (JToken)JsonConvert.DeserializeObject(templateString)); 
    } 

    public static JToken Serialize(object data, JToken template) 
    { 
     var visitor = new JsonTemplateVisitor(data); 

     return visitor.Visit(template); 
    } 

    protected override JToken VisitValue(JValue value) 
    { 
     if (value.Type == JTokenType.String) 
     { 
      var s = (string)value.Value; 

      if (s.StartsWith("$")) 
      { 
       string path = s.Substring(1); 

       var newValue = GetValue(m_data, path); 

       var newValueToken = new JValue(newValue); 

       value.Replace(newValueToken); 

       return newValueToken; 
      } 
     } 

     return value; 
    } 

    private static object GetValue(object data, string path) 
    { 
     var parts = path.Split('.'); 

     foreach (var part in parts) 
     { 
      if (data == null) 
       break; 

      data = data.GetType() 
       .GetProperty(part) 
       .GetValue(data, null); 
     } 

     return data; 
    } 
} 

L'utilizzo è quindi semplice.Ad esempio, con la seguente configurazione:

{ 
    id : "$Key", 
    name: "$Name", 
    additionalInfo: 
    { 
     related: [ "$Related.Name" ] 
    } 
} 

È possibile utilizzare il codice come questo:

JsonTemplateVisitor.Serialize(data, templateString) 

Il risultato appare allora come questo:

{ 
    "id": "someKey", 
    "name": "Isaac", 
    "additionalInfo": { 
    "related": [ 
     "Arthur" 
    ] 
    } 
} 

si potrebbe desiderare di aggiungere un po 'l'errore -check, ma a parte questo, il codice dovrebbe funzionare. Inoltre, utilizza la riflessione, quindi potrebbe non essere adatto se le prestazioni sono importanti.

+0

Ci proverò domani. Sembra promettente! Grazie per lo sforzo. –

0

Non sei troppo sicuro di cosa intendi con un modello, se stai cercando il serializer generale di json. È possibile trovare uno dei serializzatori Json più veloci per .NET in http://servicestack.net/.

Per installare questo pacchetto dalla console del gestore pacchetti è possibile eseguire il seguente comando.

 PM> Install-Package ServiceStack.Text 
+0

Sembra che non risponda alla domanda. Non si tratta solo di serializzatore JSON. – svick

+0

Svick ha ragione, sto cercando sia un serializzatore che un modo per definire le proprietà che desidero serializzare. –

+1

@ KeesC.Bakker Non capisco perché ho avuto un downvote? Ho pensato di aver chiarito nella mia risposta che, non ho capito cosa intendi con il template e la mia risposta era solo per la serializzazione json. Ora con l'immagine so esattamente cosa vuoi ottenere. – ASetty

0

ServiceStack sembra una buona scelta. enter image description here

http://www.servicestack.net/benchmarks/

+1

Sembra che non risponda alla domanda. Non si tratta solo di serializzatore JSON. – svick

+0

Svick ha ragione, sto cercando sia un serializzatore che un modo per definire le proprietà che desidero serializzare. –

+1

@svick, downvote per cosa? Quando ho aggiunto la mia risposta, @ Kees C. Bakker non ha ancora caricato le sue 1000 parole. – ValidfroM

Problemi correlati