2012-03-05 36 views
11

Tôi có một luồng dữ liệu json chứa một trường có tên là "type". Trường loại này mô tả loại đối tượng cần được tạo khi chạy. Có vẻ như tôi không thể sử dụng JsonTextReader hai lần và tôi không thể tìm thấy cách đặt lại trình đọc văn bản ở đầu.Cách sử dụng JsonTextReader hai lần

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

Tôi nhận được thông báo lỗi này. Mã thông báo không mong muốn trong khi đối tượng deserializing: EndObject.

Trả lời

10

Bạn có thể tạo JsonReader từ JToken.

JsonReader reader = token.CreateReader(); 
+0

Điều đó đã làm các trick! Cảm ơn. – Phil

0

Tôi đã làm một số thử nghiệm khác và nhận thấy rằng các công trình sau đây.

  1. Set JsonTextReader.CloseInput = false
  2. Phá hủy JsonTextReader (bằng cách đóng tuyên bố using)
  3. Đặt StreamReader.BaseStream.Position = 0
  4. Tạo mới JsonTextReader

Nó sẽ giống như thế này:

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

Điều này sẽ không hoạt động. Trừ khi bạn chỉ định tham số 'leaveOpen' trong hàm tạo' StreamReader', nó sẽ đóng luồng cơ bản. Nếu bạn sửa lỗi đó, điều này có thể hoạt động nếu mã trong câu hỏi đã hoạt động, nhưng nó không hoạt động. – svick

+0

Bài đăng gốc của tôi đã được kiểm tra nhưng không chính xác. Tôi đã cập nhật nó. – tstuts

1

Để thiết lập lại đọc của bạn để begginning, thiết lập thuộc tính Vị trí của dòng cơ bản để 0.

streamReader.BaseStream.Position = 0; 

Edit: Trong khi điều này sẽ thiết lập lại dòng cơ bản của bạn, jsonTextReader là về phía trước chỉ theo định nghĩa , có nghĩa là số dòng và vị trí của nó là chỉ đọc. Để làm việc này, bạn sẽ phải đặt lại vị trí streamReader, sau đó đưa nó vào một đối tượng J2Text36eader mới.

Rất tiếc, không có cách nào để đọc JsonTextReader hai lần vì nó chỉ chuyển tiếp.

Tham chiếu: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm "Đại diện cho người đọc cung cấp truy cập nhanh, không được lưu trữ, chuyển tiếp chỉ tới dữ liệu Json được tuần tự hóa".

+0

Bạn có chắc chắn điều này sẽ hoạt động chính xác không? Cả hai 'StreamReader' và' JsonTextReader' có thể giữ trạng thái bên trong sẽ không được thiết lập lại bằng cách thực hiện điều này. – svick

0

tôi bao gồm sử dụng JsonTextReader trong một định dạng bộ nhớ hiệu quả, tránh các đối tượng lớn Heap, vv in my blog, theo khuyến nghị James Newton King. Bạn có thể tận dụng mã này và mã được cung cấp để đọc nhiều lần JSON của bạn mà không phải lo lắng về việc triển khai bên dưới là JsonTextReader.

Nhận xét và phản hồi luôn được chào đón.

Các vấn đề liên quan