2014-10-27 66 views
3

我正在使用Vert.x爲我的類Java數據庫服務製作REST api。 這不是太難治寫JSON結果作爲字符串請求的流,如下圖所示:如何在Vert.x中使用傑克遜的JSON結果流(Java)

... 
routeMatcher.get("/myservice/api/v1/query/:query", req -> { 

    // get query 
    String querySring = req.params().get("query");   
    Query query = jsonMapper.readValue(querySring, Query.class); 

    // my service creates a list of resulting records... 
    List<Record> result = myservice.query(query);     
    String jsonResult = jsonMapper.writeValueAsString(result); 

    // write entire string to response 
    req.response().headers().set("Content-Type", "application/json; charset=UTF-8"); 
    req.response().end(jsonResult);  
}); 
... 

不過,我想用傑克遜的方法以流式Java列表請求對象:

ObjectMapper objectMapper = new ObjectMapper(); 
objectMapper.writeValue(Outputstream, result); 

但我不知道如何傑克遜的OutputStream參數連接到Vert.x的re.response(),因爲他們有自己的Buffer系統,似乎與傑克遜的java.io.OutputStream中的說法不符。

我不能將Jackson與Vert.x結合使用嗎?我應該用Vert.x自己的JSON library手動編寫自定義序列化程序嗎?其他建議?

回答

2

我假設你產生巨大的JSON文件作爲小的字符串輸出是不夠好:objectMapper.writeValue(<String>, result);

有與流的問題。 ObjectMapper不知道結果的大小,你將結束與例外:

java.lang.IllegalStateException: You must set the Content-Length header to be the total size of the message body BEFORE sending any data if you are not using HTTP chunked encoding. 
     at org.vertx.java.core.http.impl.DefaultHttpServerResponse.write(DefaultHttpServerResponse.java:474) 

所以在你的榜樣,我會用臨時文件的JSON輸出,然後將它們沖洗到響應(我沒有測試的代碼)

File tmpFile = File.createTempFile("tmp", ".json"); 
mapper.writeValue(tmpFile, result); 
req.response().sendFile(tmpFile.getAbsolutePath(), (result) -> tmpFile.delete()); 

如果你知道內容的長度一開始,你可以使用下面的代碼與WriteStream

import org.vertx.java.core.buffer.Buffer; 
import org.vertx.java.core.streams.WriteStream; 

import java.io.IOException; 
import java.io.OutputStream; 

public class OutputWriterStream extends OutputStream { 

    public WriteStream writeStream; 
    public Runnable closeHandler; 

    @Override 
    public void write(int b) throws IOException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public void write(byte[] b, int off, int len) throws IOException { 
     if (off == 0 && len == b.length) { 
      writeStream.write(new Buffer(b)); 
      return; 
     } 

     byte[] bytes = new byte[len]; 
     System.arraycopy(b, off, bytes, 0, len); 
     writeStream.write(new Buffer(bytes)); 
    } 

    @Override 
    public void write(byte[] b) throws IOException { 
     writeStream.write(new Buffer(b)); 
    } 

    @Override 
    public void close() throws IOException { 
     closeHandler.run(); 
    } 
} 
2

地圖OutputStream這可能是一個(更新爲Vertx3)回答:

import io.vertx.core.file.AsyncFile; 
import io.vertx.core.buffer.Buffer; 
import io.vertx.core.http.HttpServerResponse; 
import io.vertx.core.streams.WriteStream; 

import java.io.IOException; 
import java.io.OutputStream; 

public class OutputWriterStream extends OutputStream { 

    public OutputWriterStream(final WriteStream response) { 
     this.response = response; 
     this.buffer = new byte[8192]; 
    } 

    @Override 
    public synchronized void write(final int b) throws IOException { 
     buffer[counter++] = (byte) b; 

     if (counter >= buffer.length) { 
      flush(); 
     } 
    } 

    @Override 
    public void flush() throws IOException { 
     super.flush(); 

     if (counter > 0) { 
      byte[] remaining = buffer; 

      if (counter < buffer.length) { 
       remaining = new byte[counter]; 

       System.arraycopy(buffer, 0, remaining, 0, counter); 
      } 

      response.write(Buffer.buffer(remaining)); 
      counter = 0; 
     } 
    } 

    @Override 
    public void close() throws IOException { 
     flush(); 

     super.close(); 

     if (response instanceof HttpServerResponse) { 
      try { 
       response.end(); 
      } 
      catch (final IllegalStateException ignore) { 
      } 
     } 
     else if (response instanceof AsyncFile) { 
      ((AsyncFile) response).close(); 
     } 
    } 

    private final WriteStream<Buffer> response; 
    private final byte[] buffer; 
    private int counter = 0; 

}