From de07f1c9b5648c6c20fe2d5fb497d6c879e9c1b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volkan=20Yaz=C4=B1c=C4=B1?= Date: Fri, 10 Jan 2020 19:06:06 +0100 Subject: [PATCH] test for #587 (#589) Fix #587 Add JsonGenerator#writeNumber(char[],int,int) methods, tests --- .../fasterxml/jackson/core/JsonGenerator.java | 24 ++++++++++++++++++ .../filter/FilteringGeneratorDelegate.java | 21 ++++++++++++++++ .../jackson/core/json/UTF8JsonGenerator.java | 25 ++++++++++++++++++- .../core/json/WriterBasedJsonGenerator.java | 23 +++++++++++++++++ .../core/util/JsonGeneratorDelegate.java | 3 +++ .../filter/BasicGeneratorFilteringTest.java | 21 +++++++++++++++- .../core/json/GeneratorFeaturesTest.java | 9 ++++--- 7 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java index cd9aefcac7..22a090d311 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java @@ -1357,6 +1357,30 @@ public abstract int writeBinary(Base64Variant bv, */ public abstract void writeNumber(String encodedValue) throws IOException; + + /** + * Write method that can be used for custom numeric types that can + * not be (easily?) converted to "standard" Java number types. + * Because numbers are not surrounded by double quotes, regular + * {@link #writeString} method can not be used; nor + * {@link #writeRaw} because that does not properly handle + * value separators needed in Array or Object contexts. + *

+ * Note: because of lack of type safety, some generator + * implementations may not be able to implement this + * method. For example, if a binary JSON format is used, + * it may require type information for encoding; similarly + * for generator-wrappers around Java objects or JSON nodes. + * If implementation does not implement this method, + * it needs to throw {@link UnsupportedOperationException}. + * + * @throws UnsupportedOperationException If underlying data format does not + * support numbers serialized textually AND if generator is not allowed + * to just output a String instead (Schema-based formats may require actual + * number, for example) + */ + public abstract void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException; + /* /********************************************************** /* Public API, write methods, other value types diff --git a/src/main/java/com/fasterxml/jackson/core/filter/FilteringGeneratorDelegate.java b/src/main/java/com/fasterxml/jackson/core/filter/FilteringGeneratorDelegate.java index 2c9dbfc090..114f44a630 100644 --- a/src/main/java/com/fasterxml/jackson/core/filter/FilteringGeneratorDelegate.java +++ b/src/main/java/com/fasterxml/jackson/core/filter/FilteringGeneratorDelegate.java @@ -764,6 +764,27 @@ public void writeNumber(String encodedValue) throws IOException, UnsupportedOper delegate.writeNumber(encodedValue); } + @Override + public void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException, UnsupportedOperationException + { + if (_itemFilter == null) { + return; + } + if (_itemFilter != TokenFilter.INCLUDE_ALL) { + TokenFilter state = _filterContext.checkValue(_itemFilter); + if (state == null) { + return; + } + if (state != TokenFilter.INCLUDE_ALL) { + if (!state.includeRawValue()) { // close enough? + return; + } + } + _checkParentPath(); + } + delegate.writeNumber(encodedValueBuffer, offset, length); + } + @Override public void writeBoolean(boolean v) throws IOException { diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java index 6291c7c451..5bc2c5c3a3 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java @@ -1061,6 +1061,16 @@ public void writeNumber(String encodedValue) throws IOException } } + @Override + public void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException { + _verifyValueWrite(WRITE_NUMBER); + if (_cfgNumbersAsStrings) { + _writeQuotedRaw(encodedValueBuffer, offset, length); + } else { + writeRaw(encodedValueBuffer, offset, length); + } + } + private final void _writeQuotedRaw(String value) throws IOException { if (_outputTail >= _outputEnd) { @@ -1073,7 +1083,20 @@ private final void _writeQuotedRaw(String value) throws IOException } _outputBuffer[_outputTail++] = _quoteChar; } - + + private void _writeQuotedRaw(char[] text, int offset, int length) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = _quoteChar; + writeRaw(text, offset, length); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = _quoteChar; + } + @Override public void writeBoolean(boolean state) throws IOException { diff --git a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java index cdac57a40c..3e3d3bae7e 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java +++ b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java @@ -836,6 +836,16 @@ public void writeNumber(String encodedValue) throws IOException } } + @Override + public void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException { + _verifyValueWrite(WRITE_NUMBER); + if (_cfgNumbersAsStrings) { + _writeQuotedRaw(encodedValueBuffer, offset, length); + } else { + writeRaw(encodedValueBuffer, offset, length); + } + } + private void _writeQuotedRaw(String value) throws IOException { if (_outputTail >= _outputEnd) { @@ -849,6 +859,19 @@ private void _writeQuotedRaw(String value) throws IOException _outputBuffer[_outputTail++] = _quoteChar; } + private void _writeQuotedRaw(char[] text, int offset, int length) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = _quoteChar; + writeRaw(text, offset, length); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = _quoteChar; + } + @Override public void writeBoolean(boolean state) throws IOException { diff --git a/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java b/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java index e0ae9e3cd5..ac862747be 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java +++ b/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java @@ -336,6 +336,9 @@ public void writeString(Reader reader, int len) throws IOException { @Override public void writeNumber(String encodedValue) throws IOException, UnsupportedOperationException { delegate.writeNumber(encodedValue); } + @Override + public void writeNumber(char[] encodedValueBuffer, int offset, int length) throws IOException, UnsupportedOperationException { delegate.writeNumber(encodedValueBuffer, offset, length); } + @Override public void writeBoolean(boolean state) throws IOException { delegate.writeBoolean(state); } diff --git a/src/test/java/com/fasterxml/jackson/core/filter/BasicGeneratorFilteringTest.java b/src/test/java/com/fasterxml/jackson/core/filter/BasicGeneratorFilteringTest.java index 8419541a4e..7e4661c1d1 100644 --- a/src/test/java/com/fasterxml/jackson/core/filter/BasicGeneratorFilteringTest.java +++ b/src/test/java/com/fasterxml/jackson/core/filter/BasicGeneratorFilteringTest.java @@ -435,7 +435,7 @@ public void testWriteStartObjectWithObject() throws Exception } // [core#580] - public void testRawValueDelegation() throws Exception + public void testRawValueDelegationWithArray() throws Exception { StringWriter w = new StringWriter(); FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), @@ -453,4 +453,23 @@ public void testRawValueDelegation() throws Exception gen.close(); assertEquals("[1,3,/* comment */,42]", w.toString()); } + + // [core#588] + public void testRawValueDelegationWithObject() throws Exception + { + StringWriter w = new StringWriter(); + FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(ObjectWriteContext.empty(), w), + TokenFilter.INCLUDE_ALL, true, true); + + gen.writeStartObject(); + gen.writeNumberField("f1", 1); + gen.writeFieldName("f2"); + gen.writeRawValue(new char[]{'1', '2', '.', '3', '-'}, 0, 4); + gen.writeNumberField("f3", 3); + gen.writeEndObject(); + + gen.close(); + assertEquals(aposToQuotes("{'f1':1,'f2':12.3,'f3':3}"), w.toString()); + } + } diff --git a/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java b/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java index 11aa231977..b42a734765 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java +++ b/src/test/java/com/fasterxml/jackson/core/json/GeneratorFeaturesTest.java @@ -95,16 +95,16 @@ public void testNumbersAsJSONStrings() throws IOException { JsonFactory f = new JsonFactory(); // by default should output numbers as-is: - assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1]", _writeNumbers(f, false)); - assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1]", _writeNumbers(f, true)); + assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3]", _writeNumbers(f, false)); + assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3]", _writeNumbers(f, true)); // but if overridden, quotes as Strings f = JsonFactory.builder() .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS) .build(); - assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\"]", + assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\"]", _writeNumbers(f, false)); - assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\"]", + assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\"]", _writeNumbers(f, true)); @@ -227,6 +227,7 @@ private String _writeNumbers(JsonFactory f, boolean useBytes) throws IOException g.writeNumber(BigInteger.valueOf(3001)); g.writeNumber(BigDecimal.valueOf(0.5)); g.writeNumber("-1"); + g.writeNumber(new char[]{'1', '2', '.', '3', '-'}, 0, 4); g.writeEndArray(); g.close();