From c58069f2849837aaaaa13aa4cb00b83c32966623 Mon Sep 17 00:00:00 2001 From: ikurovsky Date: Thu, 5 Apr 2018 08:58:14 +0300 Subject: [PATCH] Better handling of streaming JSON data in JsonObjectDecoder (#7821) Motivation: When the JsonObjectDecoder determines that the incoming buffer had some data discarded, it resets the internal index to readerIndex and attempts to adjust the state which does not correctly work for streams of JSON objects. Modifications: Reset the internal index to the value considering the previous reads. Result: JsonObjectDecoder correctly handles streams of both JSON objects and arrays with no state adjustments or repeatable reads. --- .../handler/codec/json/JsonObjectDecoder.java | 6 +----- .../codec/json/JsonObjectDecoderTest.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java b/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java index 123618b143..f63e62066e 100644 --- a/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java @@ -91,11 +91,7 @@ public class JsonObjectDecoder extends ByteToMessageDecoder { } if (this.idx > in.readerIndex() && lastReaderIndex != in.readerIndex()) { - this.idx = in.readerIndex(); - if (state == ST_DECODING_ARRAY_STREAM) { - insideString = false; - openBraces = 1; - } + this.idx = in.readerIndex() + (idx - lastReaderIndex); } // index of next byte to process. diff --git a/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java index 12eb13ac19..d29654f249 100644 --- a/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java @@ -47,6 +47,27 @@ public class JsonObjectDecoderTest { assertFalse(ch.finish()); } + @Test + public void testMultipleJsonObjectsOverMultipleWrites() { + EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); + + String objectPart1 = "{\"name\":\"Jo"; + String objectPart2 = "hn\"}{\"name\":\"John\"}{\"name\":\"Jo"; + String objectPart3 = "hn\"}"; + + ch.writeInbound(Unpooled.copiedBuffer(objectPart1, CharsetUtil.UTF_8)); + ch.writeInbound(Unpooled.copiedBuffer(objectPart2, CharsetUtil.UTF_8)); + ch.writeInbound(Unpooled.copiedBuffer(objectPart3, CharsetUtil.UTF_8)); + + for (int i = 0; i < 3; i++) { + ByteBuf res = ch.readInbound(); + assertEquals("{\"name\":\"John\"}", res.toString(CharsetUtil.UTF_8)); + res.release(); + } + + assertFalse(ch.finish()); + } + @Test public void testJsonArrayOverMultipleWrites() { EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder());