2011-11-06 14 views
6

Che cosa ho I modelli sono memorizzati in un database e dati JSON che vengono convertiti in un dizionario in C#.Quale approccio alla modellazione in C# dovrei prendere?

Esempio:

Template: "Ciao {FirstName}"

dati: "{FirstName: 'Jack'}"

Questo funziona facilmente con un livello di dati utilizzando un'espressione regolare per estrarre qualsiasi cosa all'interno di {} nel modello.

Cosa voglio Mi piacerebbe essere in grado di andare più in profondità nel JSON rispetto al primo livello.

Esempio:

Template: "Ciao {Nome: {Prima}}"

dati: "{nome: {Prima: 'Jack', Ultimo: 'Smith'}}"

Quale approccio dovrei prendere? (E alcune indicazioni su dove iniziare con la vostra scelta)

  1. Un'espressione regolare
  2. Non utilizzare JSON nel modello (a favore di XSLT o qualcosa di simile)
  3. Qualcos'altro

Mi piacerebbe anche essere in grado di scorrere i dati nel modello, ma non ho idea di dove cominciare con quello!

Grazie cumuli

risposta

2

Ecco come lo farei:

Cambiare il modello in questo formato Hi {Name.First}

Ora creare un JavaScriptSerializer per convertire JSON in Dictionary<string, object>

JavaScriptSerializer jss = new JavaScriptSerializer(); 
dynamic d = jss.Deserialize(data, typeof(object)); 

Ora la variabile d ha i valori della vostra JSON in un dizionario.

Avendo che è possibile eseguire il modello contro un regex per sostituire {X.Y.Z.N} con le chiavi del dizionario, in modo ricorsivo.

completa Esempio:

public void Test() 
{ 
    // Your template is simpler 
    string template = "Hi {Name.First}"; 

    // some JSON 
    string data = @"{""Name"":{""First"":""Jack"",""Last"":""Smith""}}"; 

    JavaScriptSerializer jss = new JavaScriptSerializer(); 

    // now `d` contains all the values you need, in a dictionary 
    dynamic d = jss.Deserialize(data, typeof(object)); 

    // running your template against a regex to 
    // extract the tokens that need to be replaced 
    var result = Regex.Replace(template, @"{?{([^}]+)}?}", (m) => 
     { 
      // Skip escape values (ex: {{escaped value}}) 
      if (m.Value.StartsWith("{{")) 
       return m.Value; 

      // split the token by `.` to run against the dictionary 
      var pieces = m.Groups[1].Value.Split('.'); 
      dynamic value = d; 

      // go after all the pieces, recursively going inside 
      // ex: "Name.First" 

      // Step 1 (value = value["Name"]) 
      // value = new Dictionary<string, object> 
      // { 
      //  { "First": "Jack" }, { "Last": "Smith" } 
      // }; 

      // Step 2 (value = value["First"]) 
      // value = "Jack" 

      foreach (var piece in pieces) 
      { 
       value = value[piece]; // go inside each time 
      } 

      return value; 
     }); 
} 

non ho gestire le eccezioni (ad esempio, il valore non è stato trovato), è in grado di gestire questo caso e restituire il valore corrispondente, se non è stato trovato. m.Value per il valore grezzo o m.Groups[1].Value per la stringa tra {}.

2

Avete pensato di utilizzare JavaScript come linguaggio di scripting? Ho avuto un grande successo con Jint, anche se il costo di avvio è elevato. Un'altra opzione è Jurassic, che non ho usato io stesso.

Se si dispone di un'applicazione Web, utilizzare Razor può essere un'idea, see here.

L'utilizzo di Regex o qualsiasi tipo di parsing di stringhe può certamente funzionare per cose banali, ma può diventare doloroso quando si desidera la logica o anche solo gerarchie di base. Se si deserializzare tuo JSON in Dizionari nidificate, è possibile costruire un parser in modo relativamente semplice:

// Untested and error prone, just to illustrate the concept 
var parts = "parentObj.childObj.property".split('.'); 
Dictionary<object,object> current = yourDeserializedObject; 
foreach(var key in parts.Take(parts.Length-1)){ 
    current = current[key]; 
} 
var value = current[parts.Last()]; 

Proprio qualunque cosa tu faccia, non fanno XSLT. In realtà, se XSLT è la risposta allora la domanda deve essere stata davvero disperata :)

+0

Questo suona come lo scenario perfetto per XSLT. –

+0

Solo se ti piace la verbosità che porta con sé. –

+0

Il mio capo sarebbe d'accordo con te Kirk, ma come dice Michael, è un po 'grande per quello che sto cercando di fare. E grazie mille Michael, la tua risposta è ottima, ma puoi dare solo un segno di spunta :) –

4

Sei fortunato! SmartFormat fa esattamente come descrivi. È un'utilità di formattazione delle stringhe leggera e open source.

Supporta nome segnaposto:

var template = " {Name:{Last}, {First}} "; 

var data = new { Name = new { First="Dwight", Last="Schrute" } }; 

var result = Smart.Format(template, data); 
// Outputs: " Schrute, Dwight " SURPRISE! 

Supporta anche lista formattazione:

var template = " {People:{}|, |, and} "; 

var data = new { People = new[]{ "Dwight", "Michael", "Jim", "Pam" } }; 

var result = Smart.Format(template, data); 
// Outputs: " Dwight, Michael, Jim, and Pam " 

È possibile controllare i test di unità per Named Placeholders e List Formatter di vedere un sacco altri esempi!

Ha anche diverse forme di gestione degli errori (errori di ignorare, errori di output, errori di lancio).

Nota: il nome segnaposto funzione utilizza la riflessione e/o ricerche del dizionario, in modo da poter deserializzare il JSON in C# oggetti o nidificato Dictionaries, e funzionerà grande!

Problemi correlati