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.
This commit is contained in:
ikurovsky 2018-04-05 08:58:14 +03:00 committed by Norman Maurer
parent 0f4001d598
commit c58069f284
2 changed files with 22 additions and 5 deletions

View File

@ -91,11 +91,7 @@ public class JsonObjectDecoder extends ByteToMessageDecoder {
} }
if (this.idx > in.readerIndex() && lastReaderIndex != in.readerIndex()) { if (this.idx > in.readerIndex() && lastReaderIndex != in.readerIndex()) {
this.idx = in.readerIndex(); this.idx = in.readerIndex() + (idx - lastReaderIndex);
if (state == ST_DECODING_ARRAY_STREAM) {
insideString = false;
openBraces = 1;
}
} }
// index of next byte to process. // index of next byte to process.

View File

@ -47,6 +47,27 @@ public class JsonObjectDecoderTest {
assertFalse(ch.finish()); 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 @Test
public void testJsonArrayOverMultipleWrites() { public void testJsonArrayOverMultipleWrites() {
EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder());