From ca17d2fcbfe76eff578c80c21cc2774befcea6f3 Mon Sep 17 00:00:00 2001 From: LokeshN Date: Wed, 18 May 2016 13:08:55 +0530 Subject: [PATCH] issue #15 - readtext in jsonparser --- .../fasterxml/jackson/core/JsonParser.java | 10 +++ .../core/json/ReaderBasedJsonParser.java | 46 ++++++++++ .../core/json/UTF8DataInputJsonParser.java | 46 ++++++++++ .../core/json/UTF8StreamJsonParser.java | 46 ++++++++++ .../jackson/core/util/JsonParserDelegate.java | 2 + .../jackson/core/util/TextBuffer.java | 10 +++ .../jackson/core/read/JsonParserTest.java | 84 +++++++++++++++++++ 7 files changed, 244 insertions(+) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonParser.java b/src/main/java/com/fasterxml/jackson/core/JsonParser.java index 8e1aee1585..9dd27b8471 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonParser.java @@ -1030,6 +1030,16 @@ public int currentTokenId() { */ public abstract String getText() throws IOException; + /** + * Method to read the textual representation of the current token in chunks and + * pass it to the given Writer + * + * @return The number of characters written to the Writer + * + * @since 2.8 + */ + public abstract int readText(Writer writer) throws IOException, UnsupportedOperationException; + /** * Method similar to {@link #getText}, but that will return * underlying (unmodifiable) character array that contains diff --git a/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java index a3b251d3ee..8018086fbc 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.core.json; import java.io.*; +import java.util.List; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserBase; @@ -273,6 +274,51 @@ public final String getText() throws IOException return _getText2(t); } + @Override + public final int readText(Writer writer) throws IOException, UnsupportedOperationException { + JsonToken t = _currToken; + //Stores the length of the bytes read + int len = 0; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + List segments = _textBuffer.getCharacterSegments(); + + //Indicates the currently read text buffer index which refers to the + //TextBuffer character segment + int readTextBufferIndex = 0; + //if there are character segments, then use them and write them to the writer + while(segments != null && readTextBufferIndex < segments.size()) { + writer.write(segments.get(readTextBufferIndex)); + len += segments.get(readTextBufferIndex).length; + readTextBufferIndex++; + } + //if there are no character segments left, then read the string from the current segment, and + //write them directly to the buffer + writer.write(_textBuffer.getCurrentSegment(), 0, _textBuffer.getCurrentSegmentSize()); + len += _textBuffer.getCurrentSegmentSize(); + + } + else if(t != null) { + switch (t.id()) { + case ID_FIELD_NAME: + writer.write(_parsingContext.getCurrentName()); + break; + case ID_STRING: + case ID_NUMBER_INT: + case ID_NUMBER_FLOAT: + writer.write(_textBuffer.contentsAsString()); + break; + default: + writer.write(t.asString()); + } + } + + return len; + } + // // // Let's override default impls for improved performance // @since 2.1 diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java index ecd94d9526..641bf3e3c8 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java @@ -2,6 +2,7 @@ import java.io.*; import java.util.Arrays; +import java.util.List; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserBase; @@ -184,6 +185,51 @@ public String getText() throws IOException return _getText2(_currToken); } + @Override + public final int readText(Writer writer) throws IOException, UnsupportedOperationException { + JsonToken t = _currToken; + //Stores the length of the bytes read + int len = 0; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + List segments = _textBuffer.getCharacterSegments(); + + //Indicates the currently read text buffer index which refers to the + //TextBuffer character segment + int readTextBufferIndex = 0; + //if there are character segments, then use them and write them to the writer + while(segments != null && readTextBufferIndex < segments.size()) { + writer.write(segments.get(readTextBufferIndex)); + len += segments.get(readTextBufferIndex).length; + readTextBufferIndex++; + } + //if there are no character segments left, then read the string from the current segment, and + //write them directly to the buffer + writer.write(_textBuffer.getCurrentSegment(), 0, _textBuffer.getCurrentSegmentSize()); + len += _textBuffer.getCurrentSegmentSize(); + + } + else if(t != null) { + switch (t.id()) { + case ID_FIELD_NAME: + writer.write(_parsingContext.getCurrentName()); + break; + case ID_STRING: + case ID_NUMBER_INT: + case ID_NUMBER_FLOAT: + writer.write(_textBuffer.contentsAsString()); + break; + default: + writer.write(t.asString()); + } + } + + return len; + } + // // // Let's override default impls for improved performance @Override public String getValueAsString() throws IOException diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java index 531070d42d..6240258e17 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java @@ -2,6 +2,7 @@ import java.io.*; import java.util.Arrays; +import java.util.List; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserBase; @@ -318,6 +319,51 @@ public String getText() throws IOException } return _getText2(_currToken); } + + @Override + public final int readText(Writer writer) throws IOException, UnsupportedOperationException { + JsonToken t = _currToken; + //Stores the length of the bytes read + int len = 0; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + List segments = _textBuffer.getCharacterSegments(); + + //Indicates the currently read text buffer index which refers to the + //TextBuffer character segment + int readTextBufferIndex = 0; + //if there are character segments, then use them and write them to the writer + while(segments != null && readTextBufferIndex < segments.size()) { + writer.write(segments.get(readTextBufferIndex)); + len += segments.get(readTextBufferIndex).length; + readTextBufferIndex++; + } + //if there are no character segments left, then read the string from the current segment, and + //write them directly to the buffer + writer.write(_textBuffer.getCurrentSegment(), 0, _textBuffer.getCurrentSegmentSize()); + len += _textBuffer.getCurrentSegmentSize(); + + } + else if(t != null) { + switch (t.id()) { + case ID_FIELD_NAME: + writer.write(_parsingContext.getCurrentName()); + break; + case ID_STRING: + case ID_NUMBER_INT: + case ID_NUMBER_FLOAT: + writer.write(_textBuffer.contentsAsString()); + break; + default: + writer.write(t.asString()); + } + } + + return len; + } // // // Let's override default impls for improved performance diff --git a/src/main/java/com/fasterxml/jackson/core/util/JsonParserDelegate.java b/src/main/java/com/fasterxml/jackson/core/util/JsonParserDelegate.java index fc6c1ba12c..7baedc1c1a 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/JsonParserDelegate.java +++ b/src/main/java/com/fasterxml/jackson/core/util/JsonParserDelegate.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.io.OutputStream; +import java.io.Writer; import java.math.BigDecimal; import java.math.BigInteger; @@ -143,6 +144,7 @@ public JsonParser overrideFormatFeatures(int values, int mask) { @Override public char[] getTextCharacters() throws IOException { return delegate.getTextCharacters(); } @Override public int getTextLength() throws IOException { return delegate.getTextLength(); } @Override public int getTextOffset() throws IOException { return delegate.getTextOffset(); } + @Override public int readText(Writer writer) throws IOException, UnsupportedOperationException { return delegate.readText(writer); } /* /********************************************************** diff --git a/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java b/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java index 85250b178e..97df3f8006 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java +++ b/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java @@ -3,6 +3,7 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import com.fasterxml.jackson.core.io.NumberInput; @@ -506,6 +507,15 @@ public void append(String str, int offset, int len) } while (len > 0); } + /** + * Returns the raw list of character segments + * + * @return The character segments + */ + public List getCharacterSegments() { + return _segments; + } + /* /********************************************************** /* Raw access, for high-performance use: diff --git a/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java b/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java index a1953e821f..76247d25eb 100644 --- a/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java +++ b/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java @@ -615,6 +615,90 @@ private void _testGetValueAsText(int mode, boolean delegate) throws Exception } p.close(); } + + public void testReadText() throws Exception { + final String JSON = "{\"a\":\"this is a sample text for json parsing using readText() method\",\"b\":true,\"c\":null,\"d\":\"foo\"}"; + //create parser in reader mode.. + JsonParser parser = createParser(MODE_READER, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + Writer writer = new StringWriter(); + int len = parser.readText(writer); + + assertTrue("String length should be same", writer.toString().length() == "this is a sample text for json parsing using readText() method".length()); + assertEquals("Returned length should be same", len, writer.toString().length()); + + //create parser in stream mode.. + parser = createParser(MODE_INPUT_STREAM, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + writer = new StringWriter(); + len = parser.readText(writer); + + assertTrue("String length should be same", writer.toString().length() == "this is a sample text for json parsing using readText() method".length()); + assertEquals("Returned length should be same", len, writer.toString().length()); + + //create parser in data input mode.. + parser = createParser(MODE_DATA_INPUT, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + writer = new StringWriter(); + len = parser.readText(writer); + + assertTrue("String length should be same", writer.toString().length() == "this is a sample text for json parsing using readText() method".length()); + assertEquals("Returned length should be same", len, writer.toString().length()); + } + + public void testLongerReadText() throws Exception { + StringBuilder builder = new StringBuilder(); + for(int i= 0; i < 1000; i++) { + builder.append("Sample Text"+i); + } + String longText = builder.toString(); + final String JSON = "{\"a\":\""+ longText +"\",\"b\":true,\"c\":null,\"d\":\"foo\"}"; + //create parser in reader mode.. + JsonParser parser = createParser(MODE_READER, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + Writer writer = new StringWriter(); + int len = parser.readText(writer); + assertEquals("Returned length should be same", len, writer.toString().length()); + + //create parser in stream mode.. + parser = createParser(MODE_INPUT_STREAM, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + writer = new StringWriter(); + len = parser.readText(writer); + assertEquals("Returned length should be same", len, writer.toString().length()); + + //create parser in data input mode.. + parser = createParser(MODE_DATA_INPUT, JSON); + //move the token until the string field + parser.nextToken(); + parser.nextToken(); + parser.nextToken(); + + writer = new StringWriter(); + len = parser.readText(writer); + assertEquals("Returned length should be same", len, writer.toString().length()); + + } /* /**********************************************************