2012-03-05 2 views
11

Мне дан поток данных json, который содержит поле с именем «type». Это поле типа описывает тип объекта, который необходимо создать во время выполнения. Похоже, что я не могу использовать JsonTextReader дважды, и я не могу найти, чтобы сбросить текстовый редактор до начала.Как использовать JsonTextReader дважды

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

Получаю это сообщение об ошибке. Неожиданный токен при десериализации объекта: EndObject.

ответ

10

Вы можете создать JsonReader из JToken.

JsonReader reader = token.CreateReader(); 
+0

Это сделало трюк! Благодарю. – Phil

0

Я провел еще несколько испытаний и обнаружил, что следующие работы.

  1. Set JsonTextReader.CloseInput = false
  2. Уничтожить JsonTextReader (закрыв using заявление)
  3. Набор StreamReader.BaseStream.Position = 0
  4. Создать новую JsonTextReader

Это будет выглядеть примерно так:

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

Это не сработает. Если вы не укажете параметр 'leaveOpen' в конструкторе' StreamReader', он закроет базовый поток. Если вы исправили это, это может сработать, если код в вопросе работал, но это не так. – svick

+0

Мое оригинальное сообщение было протестировано, но неправильно. Я обновил его. – tstuts

1

Чтобы сбросить читателя к begginning, установите свойство позиции основного потока 0.

streamReader.BaseStream.Position = 0; 

Edit: Хотя это сброс основной поток, то jsonTextReader является вперед только по определению , что означает, что его номер строки и позиция находятся только в режиме чтения. Для этого вам придется сбросить позицию streamReader, а затем подать в новый объект JsonTextReader.

Так что, к сожалению, нет возможности прочитать JsonTextReader дважды, поскольку он доступен только для пересылки.

Ссылка: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm «Представляет читатель, что обеспечивает быстрый, без кеширования, вперед-доступ только к данным сериализованной JSon.»

+0

Вы уверены, что это правильно работает? И «StreamReader», и «JsonTextReader», вероятно, сохраняют внутреннее состояние, которое не будет сбрасываться при этом. – svick

0

Я покрываю с помощью JsonTextReader в памяти эффективный формат, избегая большого объекта Heap и т.д., in my blog в соответствии с рекомендациями Джеймса Ньютона короля. Вы можете использовать это и прилагаемый код для многократного чтения вашего JSON, не беспокоясь о базовой реализации JsonTextReader.

Комментарии и отзывы всегда приветствуются.

Смежные вопросы