2012-03-05 12 views
11

Mi viene fornito un flusso di dati json che contiene un campo denominato "tipo". Questo campo tipo descrive il tipo di oggetto che deve essere creato in fase di esecuzione. Sembra che non sia in grado di utilizzare JsonTextReader due volte e non riesco a trovare la via per reimpostare il lettore di testo all'inizio.Come utilizzare JsonTextReader due volte

using (var streamReader = new StreamReader(stream, Encoding)) 
using (var jsonTextReader = new JsonTextReader(streamReader)) 
{ 
    JToken token = JObject.Load(jsonTextReader); 
    var type = (string) token.SelectToken("type"); 
    var modelType = Type.GetType("Project." + type + ", Project"); 

    // Fails here 
    var obj = serializer.Deserialize(jsonTextReader, modelType); 
} 

Viene visualizzato questo messaggio di errore. Token imprevisto durante la deserializzazione dell'oggetto: EndObject.

risposta

10

È possibile creare un JsonReader da JToken.

JsonReader reader = token.CreateReader(); 
+0

Questo ha fatto il trucco! Grazie. – Phil

0

Ho fatto altri test e ho scoperto che i seguenti lavori.

  1. Set JsonTextReader.CloseInput = false
  2. Distruggere il JsonTextReader (chiudendo la dichiarazione using)
  3. Impostare StreamReader.BaseStream.Position = 0
  4. Creare un nuovo JsonTextReader

Sarebbe simile a questa:

using (var streamReader = new StreamReader(stream, encoding)) 
{ 
    Type modelType = null; 

    using (var jsonTextReader = new JsonTextReader(streamReader)) 
    { 
     jsonTextReader.CloseInput = false; 

     JToken token = JObject.Load(jsonTextReader); 
     string type = (string)token.SelectToken("type"); 
     modelType = Type.GetType("Project." + type + ", Project"); 
    } 

    streamReader.BaseStream.Position = 0; 

    using (var jsonTextReader = new JsonTextReader(streamReader)) 
    { 
     var obj = serializer.Deserialize(jsonTextReader, modelType); 
    } 

} 
+0

Questo non funzionerà. A meno che non si specifichi il parametro 'leaveOpen' nel costruttore di' StreamReader', chiuderà il flusso sottostante. Se lo hai risolto, questo potrebbe funzionare se il codice nella domanda ha funzionato, ma non è così. – svick

+0

Il mio post originale è stato testato, ma non correttamente. L'ho aggiornato. – tstuts

1

Per ripristinare il lettore al begginning, impostare la proprietà Posizione del flusso sottostante a 0.

streamReader.BaseStream.Position = 0; 

Edit: Anche se questo sarà ripristinare il flusso sottostante, il jsonTextReader è forward-only per definizione , il che significa che il suo numero di riga e la sua posizione sono di sola lettura. Affinché ciò funzioni, è necessario ripristinare la posizione streamReader, quindi inserirla in un nuovo oggetto JsonTextReader.

Quindi, sfortunatamente Phil, non c'è modo di leggere JsonTextReader due volte poiché è forward-only.

Riferimento: "Rappresenta un lettore che fornisce velocemente, non in cache, forward-only l'accesso ai dati serializzati JSON" http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm

+0

Sei sicuro che funzionerà correttamente? Sia 'StreamReader' che' JsonTextReader' probabilmente mantengono lo stato interno che non verrà ripristinato facendo ciò. – svick

0

copro con il JsonTextReader in un formato di memoria-efficiente, evitando il Large Object Heap, ecc, in my blog, secondo le raccomandazioni James Newton re. Puoi sfruttare questo e il codice fornito per leggere il tuo JSON più volte senza preoccuparti dell'implementazione sottostante di JsonTextReader.

Commenti e feedback sempre benvenuti.