2012-03-05 13 views
11

jestem dany strumień danych JSON, który zawiera pole o nazwie „typem”. W polu tego typu opisano typ obiektu, który należy utworzyć w środowisku wykonawczym. Wygląda na to, że nie mogę używać JsonTextReader dwa razy i nie mogę odszukać, aby zresetować czytnik tekstu na początek.Jak korzystać JsonTextReader dwukrotnie

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

Otrzymuję ten komunikat o błędzie. Nieoczekiwany token podczas deserializacji obiektu: EndObject.

Odpowiedz

10

Można utworzyć JsonReader z JToken.

JsonReader reader = token.CreateReader(); 
+0

To załatwiło sprawę! Dzięki. – Phil

0

zrobiłem trochę więcej badań i stwierdzili, że następujące prace.

  1. Set JsonTextReader.CloseInput = false
  2. Zniszcz JsonTextReader (zamykając oświadczenie using)
  3. Ustaw StreamReader.BaseStream.Position = 0
  4. Utwórz nowy JsonTextReader

To będzie wyglądać następująco:

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

To nie zadziała. Jeśli nie określisz parametru 'leaveOpen' w konstruktorze' StreamReader', to zamknie on strumień bazowy. Jeśli to naprawisz, może to działać, jeśli kod w pytaniu zadziała, ale nie działa. – svick

+0

Mój oryginalny wpis został przetestowany, ale niepoprawnie. Zaktualizowałem to. – tstuts

1

Aby zresetować czytelnika do begginning, należy ustawić właściwość położenia bazowego strumień 0.

streamReader.BaseStream.Position = 0; 

EDIT: ile to będzie zresetować podstawowych strumieni, jsonTextReader jest naprzód tylko z definicji , co oznacza, że ​​numer linii i pozycja są tylko do odczytu. Aby to zadziałało trzeba by zresetować pozycję StreamReader, następnie karmić go w nowy JsonTextReader obiektu.

Tak niestety, Phil, nie ma sposobu, aby przeczytać JsonTextReader dwa razy, ponieważ jest to tylko do przodu.

Dotyczy: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm "Reprezentuje czytnik, który zapewnia szybki, nie buforowany dostęp tylko do przodu do zserializowanych danych Json."

+0

Czy jesteś pewien, że to zadziała poprawnie? Zarówno 'StreamReader' jak i' JsonTextReader' prawdopodobnie zachowują stan wewnętrzny, który nie zostanie zresetowany przez to. – svick

0

omówię pomocą JsonTextReader w formacie pamięci efektywne, unikając dużego obiektu sterty itp in my blog, zgodnie z zaleceniami James Newton króla. Możesz wykorzystać ten i dostarczony kod, aby przeczytać swój JSON wiele razy, nie martwiąc się o podstawową implementację JsonTextReader.

Komentarze i feedback zawsze mile widziane.