2015-04-06 48 views
1

我讀了幾個類似的問題,但沒有找到任何與JObject相關的問題。這裏的問題:我有級聯的JSON對象流,即:從流加載多個連接的JSON對象

{"key1":"value1"}{"key2":"value2"}{"key3":"value3"} 

現在,我想讀這些對象逐個放入JObject。以下是我試圖做到這一點:

public class JsonStreamReader : JsonTextReader 
{ 
    public JsonStreamReader(Stream s) : base(new StreamReader(s)) {} 
} 

private void LoadJson(Stream s) 
{ 
    var r = new JsonStreamReader(s) { SupportMultipleContent = true }; 
    var obj = JObject.Load(r); 
    // ... get data from JObject ... 
} 

的這裏的問題是,JObject.Load()讀取流中的所有可用數據,但只分析第一個對象,並放棄所有的休息。 我該如何處理?

而且只是出現XY問題(爲什麼我需要這樣做): 我想通過TCP流傳輸JSON消息。因爲我使用原始的TCP流,我需要知道消息的大小來讀取它。我決定在每條消息前寫入sizemessage type的小標題,這樣我就可以將標題讀入一個小緩衝區,獲得以下消息的大小,然後完全讀取它。

+0

有沒有什麼辦法可以將JSON對象封裝到數組中並用逗號分隔它們? – krillgar

+0

@krillgar所以這將是一個單一的對象? – nitrocaster

+0

是那裏的字面json嗎?大多數API以這樣的數據格式傳遞json對象的新行分隔符,所以處理它的正確方法是逐行讀取它,將每個對象傳入JObject.Load(可能需要一種不同的方法),而不是嘗試完成所有操作立刻。 – evanmcdonnal

回答

0

好吧,我只是根據我以前使用json streaming API的經驗所做的假設提供我的答案,這些API一直提供對象換行符分隔。

private void LoadJson(StreamReader sr) 
{ 
    string token = null; 
    List<JObject> items = new List<JObject>(); 
    while (token = sr.Readline() != null) 
    { 
      var obj = JsonConvert.DeserializeObject<JObject>(token); 
      items.Add(obj); 
    } 
} 

基礎是; 1)傳遞流,停止搞砸2)在while循環中讀取每行,3)單獨反序列化每個令牌,將它們聚合到代碼中,當提供的json不是採集。

下面是一些其他的想法,因爲如果它是我的代碼,我可能會以不同的方式處理它。要麼定義一個對象來使用而不是JObject,或者如果這個json實際上是你正在使用的東西,而不是一個人爲的例子,那麼我只需要使用一個Dictionary<string,string>,並將它添加到它直接添加到列表中的鍵和值我用我的例子。 這將像var obj = JsonConvert.DeserializeObject<JObject>(token); 其次是myDict.Add(obj.SelectToken("key"), obj.SelectToken("value"))。或者,如果這會導致重複曝光,那麼你可以使用List<KeyValuePair<string, string>>並做JsonConvert.DeserializeObject<KeyValuePair<string, string>>(token);

只是爲了使數據更容易處理一些想法,它們都是意見問題。就反串行化而言,關鍵僅僅是逐個處理每個令牌。那個迴應不是'有效的json',每一行都是。你需要逐行閱讀。

我個人鄙視JObject的實現。在我看來,如果您可以在編寫代碼時爲json定義架構,那麼您絕對不應該使用JObject。您拋棄了可讀性併爲(最好的情況)輸入安全性,只需保存幾行代碼即可爲模型聲明一個類或結構。基本上,你的JSON是靜態的,所以最好把它當作對待。我看到它的方式JObject只在json.NET中公開,所以你可以做出關於如何處理作者在編譯時未知的json的運行時決定。

+0

處理換行符分隔的JSON時,如何處理換行符(在字符串中)? – nitrocaster

+0

@nitrocaster我不認爲他們是,這就是爲什麼你只從這個'Load'調用返回一個對象。 '換行符分隔JSON'並不是一些定義明確的格式,因爲我指出這個迴應在技術上是無效的json。如果你將響應複製並粘貼到json驗證器中,它會正確地告訴你它是無效的。如果您熟悉json模式(http://json-schema.org/),您也將看到無法爲該json定義模式。每一行都是有效的json blob,整個文檔是無效的。 – evanmcdonnal

+0

我要傳輸的json對象包含多行字符串。我該如何處理? – nitrocaster

3

你可以做到這一點通過JsonReader設置SupportMultipleContent爲true:

Read Multiple Fragments With JsonReader

如果使用JObject.Load與設置,然後使用JsonConvert.DeserializeObject,而不是一個問題。

+0

完美的解決方案,除了一件事:閱讀器讀取流中的所有可用數據。我希望它只讀取一個對象(因此流的位置將是原始位置+讀取對象的長度),原因有兩個:1]可能有部分對象尚未完全接收; 2]以下對象旨在由其他消息傳遞協議層讀取。 – nitrocaster