2012-06-02 92 views
2

我希望能夠使用Jackson(2)讀取json消息流(來自套接字)。無阻塞地讀取json流

有辦法通過一個閱讀器作爲源,比如做:

ObjectMapper mapper = new ObjectMapper(); 
MyObject obj = mapper.readValue(aReader, MyObject.class); 

但是這將阻止,直到整個JSON消息已經到來,我想避免這種情況。

有沒有辦法讓我有一個緩衝區,我可以繼續添加字節,並能夠詢問緩衝區是否包含特定類的完整json表示形式?
喜歡的東西:

JsonBuffer buffer = new JsonBuffer(MyObject.class); 
... 
buffer.add(readBytes); 
if (buffer.hasObject()) { 
    MyObject obj = buffer.readObject(); 
} 

感謝。

回答

3

您可以使用JsonParser來獲取單個事件/令牌(這是ObjectMapper內部使用的),並且這允許更細粒度的訪問。但是目前所有的功能都使用阻塞IO,因此無法實現所謂的非阻塞(又稱「異步」)解析。

+0

謝謝,但我確實在尋找做事的異步方式..我設法找到解決辦法並添加我自己的答案。 –

+0

是的,即將提及使用長度前綴的外部框架可能是要走的路線......但是,你可能已經知道了這種可能性。 – StaxMan

+0

我第一次通過jackson直接做,但是當看到它只實現阻塞IO時,我開始考慮其他選項。 –

2

這不是我的問題的答案,但更多的是我提出的解決方法。

我沒有處理傑克遜方面的非阻塞IO,而是在我的協議中實現了它。
發送的所有json消息都填充了一個4字節的int,它保存了消息其餘部分的長度。
現在閱讀json消息變得很容易,我只是找出長度是多少,讀取它是異步的,然後可以使用傑克遜與結果字符串。

如果有人確實知道這可以直接從傑克遜完成,我仍然有興趣知道。

2

(我知道這個線程是舊的,但由於沒有被接受的答案,我想添加我的,以防萬一人仍然讀取)。

我剛剛發佈了一個名爲Actson的新庫(https://github.com/michel-kraemer/actson)。它的工作方式幾乎和OP建議的一樣。您可以用字節來提供它,直到它返回一個或多個JSON事件。當它消耗了所有的輸入數據時,你用更多的字節提供它並獲得下一個JSON事件。這個過程一直持續到JSON文本被完全消耗。

如果您知道Aalto XML(https://github.com/FasterXML/aalto-xml),那麼您應該能夠快速熟悉Actson,因爲界面幾乎相同。

這裏有一個簡單的例子:

// JSON text to parse 
byte[] json = "{\"name\":\"Elvis\"}".getBytes(StandardCharsets.UTF_8); 

JsonParser parser = new JsonParser(StandardCharsets.UTF_8); 

int pos = 0; // position in the input JSON text 
int event; // event returned by the parser 
do { 
    // feed the parser until it returns a new event 
    while ((event = parser.nextEvent()) == JsonEvent.NEED_MORE_INPUT) { 
     // provide the parser with more input 
     pos += parser.getFeeder().feed(json, pos, json.length - pos); 

     // indicate end of input to the parser 
     if (pos == json.length) { 
      parser.getFeeder().done(); 
     } 
    } 

    // handle event 
    System.out.println("JSON event: " + event); 
    if (event == JsonEvent.ERROR) { 
     throw new IllegalStateException("Syntax error in JSON text"); 
    } 
} while (event != JsonEvent.EOF); 
+0

唯一真實的東西,它的工作原理。 –

0

我發現這個問題的一些工作液。您可以使用方法inputStream.available來檢查流中是否有一些字節,並且此方法也是非阻塞的。所以,你可以使用這個方法檢查是否有什麼東西 - 解析值,如果沒有 - 等待一段時間再次檢查。下面顯示了兩個示例。

安全的風格 - 與檢查START_OBJECT JSON令牌:

while (run.get()) { 
    if (inputStream.available() > 0) { 
     for (JsonToken jsonToken; (null != (jsonToken = jsonParser.nextToken()));) { 
      if (JsonToken.START_OBJECT.equals(jsonToken)) { 
       outputStream.onNext(jsonParser.readValueAs(tClass)); 
       break; 
      } 
     } 
    } else { 
     Thread.sleep(200); // Or can be another checking time. 
    } 
} 

或者simpliest風格:

while (run.get()) { 
    if (inputStream.available() > 0) { 
     outputStream.onNext(jsonParser.readValueAs(tClass)); 
    } else { 
     Thread.sleep(200); // Or can be another checking time. 
    } 
}