Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无阻塞地读取json流_Java_Jackson_Nonblocking - Fatal编程技术网

Java 无阻塞地读取json流

Java 无阻塞地读取json流,java,jackson,nonblocking,Java,Jackson,Nonblocking,我希望能够使用Jackson(2)读取json消息流(从套接字) 有几种方法可以将读卡器作为源传递,例如: ObjectMapper mapper = new ObjectMapper(); MyObject obj = mapper.readValue(aReader, MyObject.class); 但这将阻止整个json消息到达,我希望避免这种情况 有没有一种方法可以让我不断向缓冲区添加字节,并能够询问缓冲区是否包含特定类的完整json表示? 比如: JsonBuffer buffer

我希望能够使用Jackson(2)读取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();
}

谢谢。

您可以使用
JsonParser
获取单个事件/令牌(这是
ObjectMapper
内部使用的),这允许更细粒度的访问。但所有当前的功能都使用阻塞IO,因此无法进行所谓的非阻塞(也称为“异步”)解析


编辑:2019-09-18——更正:Jackson 2.9()增加了对非阻塞/异步JSON解析的支持(问题)

这不是我问题的答案,而是我想出的更多解决方法

我没有处理Jackson方面的非阻塞IO,而是在协议中实现了它。
发送时,所有json消息都用4字节整数填充,该整数保存消息其余部分的长度。
现在读取json消息变得很容易,我只需找出长度,异步读取它,然后就可以使用Jackson和结果字符串

如果有人知道如何直接从Jackson那里做到这一点,我仍然有兴趣知道。

(我知道这条线索很旧,但由于没有公认的答案,我想添加我的,以防万一还有人读到这篇文章)

我刚刚发布了一个名为Actson()的新库。它几乎像OP建议的那样工作。您可以向它提供字节,直到它返回一个或多个JSON事件。当它消耗了所有的输入数据后,您将向它提供更多的字节,并获取下一个JSON事件。这个过程一直持续到JSON文本被完全使用为止

如果您知道aaltoxml(),那么您应该能够快速熟悉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);

我找到了解决这个问题的有效方法。您可以使用方法
inputStream.available
检查流中是否有一些字节,该方法也是非阻塞的。所以,您可以使用这个方法来检查当是时是否有一些东西-解析值,如果没有-等待一段时间再次检查。下面是两个例子

安全样式-检查开始对象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.
    }
}
或最简单的样式:

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

Jackson支持非阻塞JSON流解析。您可以找到一个关于如何在SpringFramework5中使用它的示例。

如何使用

private fun handleActions(webSocketMessage:webSocketMessage,webSocketSession:webSocketSession):Mono{
val action=Gson().fromJson(webSocketMessage.payloadAsText,ActionWs::class.java)
返回时间(action.action){
“注册”->companyService.createCompany(action.company)
.map{webSocketSession.textMessage(jacksonObjectMapper().writeValueAsString(it))}
else->Mono.just(webSocketSession.textMessage(Gson().toJson)(CompanyInfo(0,0,0,“ACAO INVALIDA!”))
}
}

谢谢,但我确实在寻找异步方式。。我设法找到了一个解决办法,并添加了我自己的答案。是的,我正要提到带长度前缀的外部框架可能是一种方式。。。但我想你可能已经知道了这种可能性。我最初是直接通过jackson实现的,但当我看到它只实现阻塞IO时,我开始考虑其他选项。阻塞IO是一种方法——我所知道的Java JSON解析器都不支持推式解析。其他的很少(对于XML,Aalto是这样做的)。非阻塞是一个主要的PITA,我在写了一些东西之后说了这些。使用NIO是痛苦的,但除此之外,当结合诸如压缩、身份验证等东西时,事情变得非常复杂。我发现Netty使NIO变得不那么痛苦,但我同意,这并不总是正确的方法,对于身份验证,我使用阻塞IO,但对于通常的流,我需要实现NIO,只是执行得更好。
private fun handleActions(webSocketMessage: WebSocketMessage, webSocketSession: WebSocketSession): Mono<WebSocketMessage> {
    val action = Gson().fromJson(webSocketMessage.payloadAsText, ActionWs::class.java)
    return when (action.action) {
        "REGISTER" -> companyService.createCompany(action.company)
            .map { webSocketSession.textMessage(jacksonObjectMapper().writeValueAsString(it)) }
        else -> Mono.just(webSocketSession.textMessage(Gson().toJson(CompanyInfo(0, 0, 0, "ACAO INVALIDA!"))))
    }
}