2014-10-27 69 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; 

}