Handle partially decoded elements while streaming Json array

Motivation:

'insideString' and 'openBraces' need a proper handling when streaming
Json array over multiple writes and an element decoding was started but
not completed.
Related to #6969

Modifications:

If the idx is reset:
- 'insideString' has to be reset to 'false' in order to indicate that
  array element will be decoded from the beginning
- 'openBraces' has to be reset to '1' to indicate that Json array
  decoding is in progress.

Result:
Json array is properly decoded when in streaming mode
This commit is contained in:
Violeta Georgieva 2017-08-04 14:33:00 +03:00 committed by Norman Maurer
parent 348745608f
commit db4781282f
2 changed files with 68 additions and 26 deletions

View File

@ -92,6 +92,10 @@ 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;
}
}
// index of next byte to process.

View File

@ -72,35 +72,73 @@ public class JsonObjectDecoderTest {
}
@Test
public void testStreamJsonArrayOverMultipleWrites() {
public void testStreamJsonArrayOverMultipleWrites1() {
String[] array = new String[] {
" [{\"test",
"case\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\"",
" }\n\n , ",
"{\"testcase\" : \"Streaming string me",
"ssage\"} ] "
};
String[] result = new String[] {
"{\"testcase\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\" }",
"{\"testcase\" : \"Streaming string message\"}"
};
doTestStreamJsonArrayOverMultipleWrites(2, array, result);
}
@Test
public void testStreamJsonArrayOverMultipleWrites2() {
String[] array = new String[] {
" [{\"test",
"case\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\"",
" }\n\n , {\"test",
"case\" : \"Streaming string me",
"ssage\"} ] "
};
String[] result = new String[] {
"{\"testcase\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\" }",
"{\"testcase\" : \"Streaming string message\"}"
};
doTestStreamJsonArrayOverMultipleWrites(2, array, result);
}
@Test
public void testStreamJsonArrayOverMultipleWrites3() {
String[] array = new String[] {
" [{\"test",
"case\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\"",
" }\n\n , [{\"test",
"case\" : \"Streaming string me",
"ssage\"}] ] "
};
String[] result = new String[] {
"{\"testcase\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\" }",
"[{\"testcase\" : \"Streaming string message\"}]"
};
doTestStreamJsonArrayOverMultipleWrites(2, array, result);
}
private static void doTestStreamJsonArrayOverMultipleWrites(int indexDataAvailable,
String[] array, String[] result) {
EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder(true));
String arrayPart1 = "[{\"test";
String arrayPart2 = "case\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\"";
String arrayPart3 = " }\n\n , ";
String arrayPart4 = "{\"testcase\" : \"Streaming string me";
String arrayPart5 = "ssage\"} ]";
boolean dataAvailable = false;
for (String part : array) {
dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(part, CharsetUtil.UTF_8));
if (indexDataAvailable > 0) {
assertFalse(dataAvailable);
} else {
assertTrue(dataAvailable);
}
indexDataAvailable--;
}
// Test array
boolean dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(" " + arrayPart1, CharsetUtil.UTF_8));
assertFalse(dataAvailable);
dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(arrayPart2, CharsetUtil.UTF_8));
assertFalse(dataAvailable);
dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(arrayPart3, CharsetUtil.UTF_8));
assertTrue(dataAvailable);
dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(arrayPart4, CharsetUtil.UTF_8));
assertTrue(dataAvailable);
dataAvailable = ch.writeInbound(Unpooled.copiedBuffer(arrayPart5 + " ", CharsetUtil.UTF_8));
assertTrue(dataAvailable);
ByteBuf res = ch.readInbound();
assertEquals("{\"testcase\" : \"\\\"}]Escaped dou\\\"ble quotes \\\" in JSON str\\\"ing\" }",
res.toString(CharsetUtil.UTF_8));
res.release();
res = ch.readInbound();
assertEquals("{\"testcase\" : \"Streaming string message\"}", res.toString(CharsetUtil.UTF_8));
res.release();
for (String part : result) {
ByteBuf res = ch.readInbound();
assertEquals(part, res.toString(CharsetUtil.UTF_8));
res.release();
}
assertFalse(ch.finish());
}