2012-01-16 44 views
1

好吧,我之前已經提出過這樣的問題,但這是一個不同的主題,所以我覺得我應該對此做一個新的話題。我很抱歉,如果這事我不應該那樣做......如何從json流反序列化多個對象?

總之:

目前,我正在讀通過twitterfeed,並試圖將其轉換爲失去(狀態)對象。我現在的代碼如下,但失敗:

webRequest = (HttpWebRequest)WebRequest.Create(stream_url); 
webRequest.Credentials = new NetworkCredential(username, password); 
webRequest.Timeout = -1; 
webResponse = (HttpWebResponse)webRequest.GetResponse(); 
Encoding encode = Encoding.GetEncoding("utf-8"); 
responseStream = new StreamReader(webResponse.GetResponseStream(), encode); 
int i = 0; 

//Read the stream. 
while (_running) 
{ 
    jsonText = responseStream.ReadLine(); 

    byte[] sd = Encoding.Default.GetBytes(jsonText); 
    stream.Write(sd, i, i + sd.Length); 

    try 
    { 
     status s = json.ReadObject(stream) as status; 
     if (s != null) 
     { 
      //write s to a file/collection or w/e 
      i = 0; 
     } 
    } 
    catch 
    { 

    } 

} 

想法是:將流複製到另一個流。並不斷嘗試閱讀,直到發現狀態對象。 這是爲了防止溪流變小,所以它有機會成長。當然,這個流並不總是始於一個對象的開始,或者可能是腐敗的。

現在我確實找到了方法IsStartObject,我想我應該使用它。 雖然我沒有使用流的經驗,但我永遠也找不到如何使用它的好例子。

有沒有人可以向我解釋如何從流中讀取多個對象,以便我可以將它們寫入列表或w/e中。我真的找不到任何在互聯網上的好例子..

非常感謝你的嘗試!

+0

我不知道,我能理解,你爲什麼不讀所有的反應'responseStream.ReadToEnd()'和反序列化到一個類(或解析)? – 2012-01-16 22:06:15

+0

這是一個層出不窮的流(twitter feed)。 Status對象是我想要反序列化的類。但是流保持流式傳輸這些對象(沒有結束)。 – user1149942 2012-01-16 22:07:42

+0

你能分享這個網址以便我們測試它嗎? – 2012-01-16 22:12:04

回答

1

我用Json.Net庫和this extension class,使得使用的DynamicObject解析流JSON對象

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://stream.twitter.com/1/statuses/sample.json"); 
webRequest.Credentials = new NetworkCredential("...", "......"); 
webRequest.Timeout = -1; 
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); 
Encoding encode = Encoding.GetEncoding("utf-8"); 
StreamReader responseStream = new StreamReader(webResponse.GetResponseStream()); 

string line; 
while (true) 
{ 
    line = responseStream.ReadLine(); 
    dynamic obj = JsonUtils.JsonObject.GetDynamicJsonObject(line); 
    if(obj.user!=null) 
     Console.WriteLine(obj.user.screen_name + " => " + obj.text); 
} 
+0

非常有用的答案!非常感謝你,這正是我所需要的:) 但有一個問題:是否會發生這樣的情況:解析爲動態json對象發生的速度慢於流正在進入,這將導致流在內存中緩衝? 如果是這樣:我該如何解決這個問題? – user1149942 2012-01-17 10:01:26

+0

這是一個生產者 - 消費者問題。你可以在一個單獨的線程中運行reader,把'line's放到一個隊列中(例如BlockingQueue),主線程可以讀取該隊列中的行並創建一個動態對象(甚至可以處理'line's在BlockingQueue中有很多線程) – 2012-01-17 10:08:09

+0

感謝您的幫助。不過,還有一個問題:一個對象是否在同一行是正常的?當我開始時,我只是期待部分數據...就像它直到讀取一半的對象,然後下一行是下一部分等等......它總是這麼簡單,還是僅僅因爲流的提供者而不同? – user1149942 2012-01-17 21:32:55

-1

這是通過計算的嵌套層次{和} L.B的建議對分裂的實現。

public static IEnumerable<string> JsonSplit(this StreamReader input, char openChar = '{', char closeChar = '}', 
    char quote='"', char escape='\\') 
{ 
    var accumulator = new StringBuilder(); 
    int count = 0; 
    bool gotRecord = false; 
    bool inString = false; 
    while (!input.EndOfStream) 
    { 
    char c = (char)input.Read(); 
    if (c == escape) 
    { 
     accumulator.Append(c); 
     c = (char)input.Read(); 
    } 
    else if (c == quote) 
    { 
     inString = !inString; 
    } 
    else if (inString) 
    { 
    } 
    else if (c == openChar) 
    { 
     gotRecord = true; 
     count++; 
    } 
    else if (c == closeChar) 
    { 
     count--; 
    } 
    accumulator.Append(c); 
    if (count != 0 || !gotRecord) continue; 
    // now we are not within a block so 
    string result = accumulator.ToString(); 
    accumulator.Clear(); 
    gotRecord = false; 
    yield return result; 
    } 
} 

這是一個測試

[TestClass] 
    public class UnitTest1 
    { 
    [TestMethod] 
    public void TestMethod1() 
    { 
     string text = "{\"a\":1}{\"b\":\"hello\"}{\"c\":\"oh}no!\"}{\"d\":\"and\\\"also!\"}"; 
     var reader = FromStackOverflow.GenerateStreamFromString(text); 
     var e = MyJsonExtensions.JsonSplit(reader).GetEnumerator(); 
     e.MoveNext(); 
     Assert.AreEqual("{\"a\":1}", e.Current); 
     e.MoveNext(); 
     Assert.AreEqual("{\"b\":\"hello\"}", e.Current); 
     e.MoveNext(); 
     Assert.AreEqual("{\"c\":\"oh}no!\"}", e.Current); 
     e.MoveNext(); 
     Assert.AreEqual("{\"d\":\"and\\\"also!\"}", e.Current); 
    } 
    } 

GenerateStreamFromString的實施是here

+0

如果您的openChar/closeChar恰好在字符串中,則會失敗。 E.G. {「a」:1} {「b」:「hello」} {「c」:「oh} no!」} – 2016-06-14 12:15:44

+0

Thanks @GraemeJob。雖然不希望編寫json解析器,但我已經更新了我的答案以處理顯而易見的陷阱。 – jdpilgrim 2016-10-06 10:56:31