2012-03-05 28 views
11

Me dan una secuencia de datos json que contiene un campo llamado "tipo". Este campo de tipo describe el tipo de objeto que debe crearse en tiempo de ejecución. Parece que no puedo usar el JsonTextReader dos veces y no puedo encontrar la distancia para restablecer el lector de texto al principio.Cómo utilizar JsonTextReader dos veces

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); 
} 

Aparece este mensaje de error. Token inesperado al deserializar el objeto: EndObject.

Respuesta

10

Puede crear un JsonReader desde JToken.

JsonReader reader = token.CreateReader(); 
+0

¡Eso fue lo que hizo! Gracias. – Phil

0

Hice algunas pruebas más y descubrí que funciona lo siguiente.

  1. Conjunto JsonTextReader.CloseInput = false
  2. Destruye la JsonTextReader (cerrando la declaración using)
  3. Establecer StreamReader.BaseStream.Position = 0
  4. Crear un nuevo JsonTextReader

Se vería algo como esto:

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

Esto no funcionará. A menos que especifique el parámetro 'leaveOpen' en el constructor de' StreamReader', cerrará la transmisión subyacente. Si lo solucionó, esto podría funcionar si el código en la pregunta funcionó, pero no es así. – svick

+0

Mi publicación original fue probada, pero incorrectamente. Lo he actualizado – tstuts

1

para restablecer su lector a la begginning, establezca la propiedad Posición de la secuencia subyacente a 0.

streamReader.BaseStream.Position = 0; 

Editar: Aunque esto va a restablecer la secuencia subyacente, la jsonTextReader es sólo avance por definición , lo que significa que su número de línea y posición son de solo lectura. Para que esto funcione, deberá restablecer la posición de streamReader y luego incluirla en un nuevo objeto JsonTextReader.

Desafortunadamente Phil, no hay forma de leer el JsonTextReader dos veces, ya que es solo para reenvío.

Referencia: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm "representa un lector que ofrece almacenamiento en caché no, sólo avance rápido acceso, a datos JSON en serie."

+0

¿Estás seguro de que esto va a funcionar correctamente? Tanto el 'StreamReader' como' JsonTextReader' probablemente mantengan el estado interno que no se reiniciará al hacer esto. – svick

0

cubro con el JsonTextReader en un formato de memoria eficiente, evitando el objeto grande Pila, etc., in my blog, según las recomendaciones del King James Newton. Puede aprovechar esto y el código suministrado para leer su JSON varias veces sin preocuparse por la implementación subyacente de JsonTextReader.

Comentarios y comentarios siempre son bienvenidos.