diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..f6faee69 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fb68d180..4a7eeced 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,14 +22,14 @@ jobs: strategy: fail-fast: false matrix: - java_version: ['8', '11', '17'] + java_version: ['8', '11', '17', '21'] os: ['ubuntu-20.04'] env: JAVA_OPTS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: distribution: 'temurin' java-version: ${{ matrix.java_version }} @@ -57,7 +57,7 @@ jobs: run: ./mvnw -B -q -ff -ntp test - name: Publish code coverage if: github.event_name != 'pull_request' && matrix.java_version == '8' - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./target/site/jacoco/jacoco.xml diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 642d572c..528c20cd 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,18 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/JSONWriter.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/JSONWriter.java index ddcc7d1c..e6ce63c7 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/JSONWriter.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/JSONWriter.java @@ -3,6 +3,7 @@ import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; +import java.nio.file.Path; import java.util.*; import com.fasterxml.jackson.core.*; @@ -217,21 +218,30 @@ public void writeField(String fieldName, Object value, int type) throws IOExcept writeBigIntegerField(fieldName, (BigInteger) value); return; case SER_NUMBER_FLOAT: // fall through + case SER_NUMBER_FLOAT_WRAPPER: + writeFloatField(fieldName, ((Float) value).floatValue()); + return; case SER_NUMBER_DOUBLE: - writeDoubleField(fieldName, ((Number) value).doubleValue()); + case SER_NUMBER_DOUBLE_WRAPPER: + writeDoubleField(fieldName, ((Double) value).doubleValue()); return; case SER_NUMBER_BYTE: // fall through case SER_NUMBER_SHORT: // fall through - case SER_NUMBER_INTEGER: writeIntField(fieldName, ((Number) value).intValue()); return; + case SER_NUMBER_INTEGER: + case SER_NUMBER_INTEGER_WRAPPER: + writeIntField(fieldName, ((Integer) value).intValue()); + return; case SER_NUMBER_LONG: - writeLongField(fieldName, ((Number) value).longValue()); + case SER_NUMBER_LONG_WRAPPER: + writeLongField(fieldName, ((Long) value).longValue()); return; // Scalar types: case SER_BOOLEAN: + case SER_BOOLEAN_WRAPPER: writeBooleanField(fieldName, ((Boolean) value).booleanValue()); return; case SER_CHAR: @@ -257,6 +267,9 @@ public void writeField(String fieldName, Object value, int type) throws IOExcept case SER_URI: writeStringLikeField(fieldName, value.toString(), type); return; + case SER_PATH: + writeStringLikeField(fieldName, ((Path) value).toUri().toString(), type); + return; // Others @@ -327,16 +340,24 @@ protected void _writeValue(Object value, int type) throws IOException // Number types: case SER_NUMBER_FLOAT: // fall through + case SER_NUMBER_FLOAT_WRAPPER: // fall through + writeFloatValue(((Float) value).floatValue()); + return; case SER_NUMBER_DOUBLE: - writeDoubleValue(((Number) value).doubleValue()); + case SER_NUMBER_DOUBLE_WRAPPER: + writeDoubleValue(((Double) value).doubleValue()); return; case SER_NUMBER_BYTE: // fall through case SER_NUMBER_SHORT: // fall through - case SER_NUMBER_INTEGER: writeIntValue(((Number) value).intValue()); return; + case SER_NUMBER_INTEGER: + case SER_NUMBER_INTEGER_WRAPPER: + writeIntValue(((Integer) value).intValue()); + return; case SER_NUMBER_LONG: - writeLongValue(((Number) value).longValue()); + case SER_NUMBER_LONG_WRAPPER: + writeLongValue(((Long) value).longValue()); return; case SER_NUMBER_BIG_DECIMAL: writeBigDecimalValue((BigDecimal) value); @@ -348,6 +369,7 @@ protected void _writeValue(Object value, int type) throws IOException // Other scalar types: case SER_BOOLEAN: + case SER_BOOLEAN_WRAPPER: writeBooleanValue(((Boolean) value).booleanValue()); return; case SER_CHAR: @@ -375,6 +397,9 @@ protected void _writeValue(Object value, int type) throws IOException case SER_URI: writeStringLikeValue(value.toString(), type); return; + case SER_PATH: + writeStringLikeValue(((Path) value).toUri().toString(), type); + return; case SER_ITERABLE: writeIterableValue((Iterable) value); @@ -582,6 +607,14 @@ protected void writeLongField(String fieldName, long v) throws IOException { _generator.writeNumberField(fieldName, v); } + protected void writeFloatValue(float v) throws IOException { + _generator.writeNumber(v); + } + + protected void writeFloatField(String fieldName, float v) throws IOException { + _generator.writeNumberField(fieldName, v); + } + protected void writeDoubleValue(double v) throws IOException { _generator.writeNumber(v); } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/SimpleValueReader.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/SimpleValueReader.java index fa6103af..f69f914d 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/SimpleValueReader.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/SimpleValueReader.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.net.URI; import java.net.URL; +import java.nio.file.Paths; import java.util.*; import com.fasterxml.jackson.core.JsonParser; @@ -60,6 +61,7 @@ public Object readNext(JSONReader reader, JsonParser p) throws IOException // cases default to "standard" handling which does range checks etc case SER_NUMBER_INTEGER: + case SER_NUMBER_INTEGER_WRAPPER: { int i = p.nextIntValue(-2); if (i != -2) { @@ -69,6 +71,7 @@ public Object readNext(JSONReader reader, JsonParser p) throws IOException } case SER_NUMBER_LONG: + case SER_NUMBER_LONG_WRAPPER: { long l = p.nextLongValue(-2L); if (l != -2L) { @@ -80,6 +83,7 @@ public Object readNext(JSONReader reader, JsonParser p) throws IOException // Other scalar types: case SER_BOOLEAN: + case SER_BOOLEAN_WRAPPER: { Boolean b = p.nextBooleanValue(); if (b != null) { @@ -115,8 +119,16 @@ public Object read(JSONReader reader, JsonParser p) throws IOException // Number types: - case SER_NUMBER_FLOAT: // fall through + case SER_NUMBER_FLOAT_WRAPPER: + if (p.hasToken(JsonToken.VALUE_NULL)) { + return null; + } + case SER_NUMBER_FLOAT: return Float.valueOf((float) p.getValueAsDouble()); + case SER_NUMBER_DOUBLE_WRAPPER: + if (p.hasToken(JsonToken.VALUE_NULL)) { + return null; + } case SER_NUMBER_DOUBLE: return p.getValueAsDouble(); @@ -125,8 +137,16 @@ public Object read(JSONReader reader, JsonParser p) throws IOException case SER_NUMBER_SHORT: // fall through return (short) p.getValueAsInt(); + case SER_NUMBER_INTEGER_WRAPPER: + if (p.hasToken(JsonToken.VALUE_NULL)) { + return null; + } case SER_NUMBER_INTEGER: return p.getValueAsInt(); + case SER_NUMBER_LONG_WRAPPER: + if (p.hasToken(JsonToken.VALUE_NULL)) { + return null; + } case SER_NUMBER_LONG: return p.getValueAsLong(); @@ -139,14 +159,16 @@ public Object read(JSONReader reader, JsonParser p) throws IOException // Other scalar types: case SER_BOOLEAN: + case SER_BOOLEAN_WRAPPER: switch (p.currentTokenId()) { case JsonTokenId.ID_TRUE: return Boolean.TRUE; case JsonTokenId.ID_FALSE: return Boolean.FALSE; case JsonTokenId.ID_NULL: - // 07-Jul-2020, tatu: since `boolean` and `java.lang.Boolean` both handled - // here, can not (alas!) separate yet + if (_typeId == SER_BOOLEAN_WRAPPER) { + return null; + } return Boolean.FALSE; case JsonTokenId.ID_STRING: @@ -191,7 +213,7 @@ public Object read(JSONReader reader, JsonParser p) throws IOException try { return Class.forName(v); } catch (Exception e) { - throw new JSONObjectException("Failed to bind java.lang.Class from value '"+v+"'"); + throw new JSONObjectException("Failed to bind `java.lang.Class` from value '"+v+"'"); } } case SER_FILE: @@ -218,6 +240,16 @@ public Object read(JSONReader reader, JsonParser p) throws IOException return null; } return URI.create(p.getValueAsString()); + case SER_PATH: + if (p.hasToken(JsonToken.VALUE_NULL)) { + return null; + } + String v = p.getValueAsString(); + try { + return Paths.get(new URI(v)); + } catch (Exception e) { + throw new JSONObjectException("Failed to bind `java.nio.file.Path` from value '"+v+"'"); + } // case SER_MAP: // case SER_LIST: diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueLocatorBase.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueLocatorBase.java index 1ec9cd28..a2e18bc3 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueLocatorBase.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueLocatorBase.java @@ -5,6 +5,7 @@ import java.math.BigInteger; import java.net.URI; import java.net.URL; +import java.nio.file.Path; import java.util.*; import com.fasterxml.jackson.core.TreeNode; @@ -78,35 +79,40 @@ public abstract class ValueLocatorBase public final static int SER_NUMBER_BYTE = 13; public final static int SER_NUMBER_SHORT = 14; - + public final static int SER_NUMBER_INTEGER = 15; + public final static int SER_NUMBER_INTEGER_WRAPPER = 16; - public final static int SER_NUMBER_LONG = 16; + public final static int SER_NUMBER_LONG = 17; + public final static int SER_NUMBER_LONG_WRAPPER = 18; - public final static int SER_NUMBER_FLOAT = 17; + public final static int SER_NUMBER_FLOAT = 19; + public final static int SER_NUMBER_FLOAT_WRAPPER = 20; - public final static int SER_NUMBER_DOUBLE = 18; + public final static int SER_NUMBER_DOUBLE = 21; + public final static int SER_NUMBER_DOUBLE_WRAPPER = 22; - public final static int SER_NUMBER_BIG_INTEGER = 19; + public final static int SER_NUMBER_BIG_INTEGER = 23; - public final static int SER_NUMBER_BIG_DECIMAL = 20; + public final static int SER_NUMBER_BIG_DECIMAL = 24; // // // Other specific scalar types - public final static int SER_BOOLEAN = 21; - public final static int SER_CHAR = 22; - - public final static int SER_ENUM = 23; + public final static int SER_BOOLEAN = 25; + public final static int SER_BOOLEAN_WRAPPER = 26; + public final static int SER_CHAR = 27; - public final static int SER_DATE = 24; - public final static int SER_CALENDAR = 25; + public final static int SER_ENUM = 28; - public final static int SER_CLASS = 26; - public final static int SER_FILE = 27; - public final static int SER_UUID = 28; - public final static int SER_URL = 29; - public final static int SER_URI = 30; + public final static int SER_DATE = 29; + public final static int SER_CALENDAR = 30; + public final static int SER_CLASS = 31; + public final static int SER_FILE = 32; + public final static int SER_UUID = 33; + public final static int SER_URL = 34; + public final static int SER_URI = 35; + public final static int SER_PATH = 36; // since 2.17 // // // Iterate-able types @@ -114,7 +120,7 @@ public abstract class ValueLocatorBase * Anything that implements {@link java.lang.Iterable}, but not * {@link java.util.Collection}. */ - public final static int SER_ITERABLE = 31; + public final static int SER_ITERABLE = 37; /* /********************************************************************** @@ -170,19 +176,19 @@ protected int _findSimpleType(Class raw, boolean forSer) throw new IllegalArgumentException("Unrecognized primitive type: "+raw.getName()); } if (raw == Boolean.class) { - return SER_BOOLEAN; + return SER_BOOLEAN_WRAPPER; } if (Number.class.isAssignableFrom(raw)) { - if (raw == Integer.class) return SER_NUMBER_INTEGER; - if (raw == Long.class) return SER_NUMBER_LONG; - if (raw == Byte.class) return SER_NUMBER_BYTE; - if (raw == Short.class) return SER_NUMBER_SHORT; - if (raw == Double.class) return SER_NUMBER_DOUBLE; - if (raw == Float.class) return SER_NUMBER_FLOAT; + if (raw == Integer.class) return SER_NUMBER_INTEGER_WRAPPER; + if (raw == Long.class) return SER_NUMBER_LONG_WRAPPER; + if (raw == Double.class) return SER_NUMBER_DOUBLE_WRAPPER; + if (raw == Float.class) return SER_NUMBER_FLOAT_WRAPPER; if (raw == BigDecimal.class) return SER_NUMBER_BIG_DECIMAL; if (raw == BigInteger.class) { return SER_NUMBER_BIG_INTEGER; } + if (raw == Byte.class) return SER_NUMBER_BYTE; + if (raw == Short.class) return SER_NUMBER_SHORT; // What numeric type is this? Could consider "string-like" but... return SER_UNKNOWN; } @@ -231,21 +237,24 @@ protected int _findSimpleType(Class raw, boolean forSer) if (UUID.class.isAssignableFrom(raw)) { return SER_UUID; } - /* May or may not help with deser, but recognized nonetheless; - * on assumption that Beans should rarely implement `CharSequence` - */ + if (Path.class.isAssignableFrom(raw)) { + return SER_PATH; + } + // May or may not help with deser, but recognized nonetheless; + // on assumption that Beans should rarely implement `CharSequence` if (CharSequence.class.isAssignableFrom(raw)) { return SER_CHARACTER_SEQUENCE; } - /* `Iterable` can be added on all kinds of things, and it won't - * help at all with deserialization; hence only use for serialization. - */ + // `Iterable` can be added on all kinds of things, and it won't + // help at all with deserialization; hence only use for serialization. if (forSer && Iterable.class.isAssignableFrom(raw)) { - return SER_ITERABLE; + // 16-Feb-2024, tatu: [jackson-jr#112] java.nio.file.Path is not really Iterable + if (!java.nio.file.Path.class.isAssignableFrom(raw)) { + return SER_ITERABLE; + } } // Ok. I give up, no idea! return SER_UNKNOWN; } - } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java index aa3decc9..dc30fcdf 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java @@ -309,6 +309,27 @@ protected BeanPropertyWriter[] _resolveBeanForSer(Class raw, POJODefinition b f.setAccessible(true); } } + // NOTE: cannot just call `findSerializationType()` due to + // cyclic type definitions. + + int typeId; + Integer I = _knownSerTypes.get(new ClassKey(type, _features)); + + if (I != null) { + typeId = I.intValue(); + } else { + typeId = _findSimpleType(type, true); + if ((_writerModifier != null) && typeId != 0) { + ValueWriter w = _writerModifier.overrideStandardValueWriter(_writeContext, type, typeId); + if (w != null) { + typeId = _registerWriter(type, w); + } + } + // But what if none found? Discovered dynamically later on? + } + + // 16-Feb-2024, tatu: Code pre-2.17 -- remove from 2.18 if not needed + /* int typeId = _findSimpleType(type, true); // Give plugin the opportunity to override standard value writer if (_writerModifier != null && typeId != 0) { @@ -318,8 +339,11 @@ protected BeanPropertyWriter[] _resolveBeanForSer(Class raw, POJODefinition b if (w != null) { typeId = _registerWriter(type, w); } + } else { + typeId = I.intValue(); } } + */ props.add(new BeanPropertyWriter(typeId, rawProp.name, rawProp.field, m)); } int plen = props.size(); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/NullHandling78Test.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/NullHandling78Test.java deleted file mode 100644 index 14b54e0f..00000000 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/NullHandling78Test.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.fasterxml.jackson.jr.failing; - -import java.util.LinkedHashMap; -import java.util.Map; - -import com.fasterxml.jackson.jr.ob.JSON; -import com.fasterxml.jackson.jr.ob.TestBase; - -public class NullHandling78Test extends TestBase -{ - // [jackson-jr#78] - static class IntegerWrapper { - public Integer value; - } - static class IntPrimitiveWrapper { - public int value; - } - static class LongWrapper { - public Long value; - } - static class LongPrimitiveWrapper { - public long value; - } - static class BooleanWrapper { - public Boolean value; - } - static class BooleanPrimitiveWrapper { - public boolean value; - } - static class DoubleWrapper { - public Double value; - } - static class DoublePrimitiveWrapper { - public double value; - } - - // Test to verify that outputting of nulls is configurable - public void testMapNullEntries() throws Exception - { - Map map = new LinkedHashMap(); - map.put("a", 1); - map.put("b", null); - // By default we do NOT write null-valued entries: - assertEquals("{\"a\":1}", JSON.std.asString(map)); - // but we can disable it easily - assertEquals("{\"a\":1,\"b\":null}", - JSON.std.with(JSON.Feature.WRITE_NULL_PROPERTIES).asString(map)); - } - - // [jackson-jr#78], int/Integer - - public void testIntPrimitive() throws Exception - { - IntPrimitiveWrapper w = JSON.std.beanFrom(IntPrimitiveWrapper.class, - a2q("{'value':1}")); - assertEquals(1, w.value); - - w = JSON.std.beanFrom(IntPrimitiveWrapper.class, - a2q("{'value':null}")); - assertEquals(0, w.value); - } - - public void testIntWrapper() throws Exception - { - IntegerWrapper w = JSON.std.beanFrom(IntegerWrapper.class, - a2q("{'value':1}")); - assertEquals(Integer.valueOf(1), w.value); - - w = JSON.std.beanFrom(IntegerWrapper.class, - a2q("{'value':null}")); - assertNull(w.value); - } - - // [jackson-jr#78], long/Long - - public void testLongPrimitive() throws Exception - { - LongPrimitiveWrapper w = JSON.std.beanFrom(LongPrimitiveWrapper.class, - a2q("{'value':2}")); - assertEquals(2L, w.value); - - w = JSON.std.beanFrom(LongPrimitiveWrapper.class, - a2q("{'value':null}")); - assertEquals(0L, w.value); - } - - public void testLongWrapper() throws Exception - { - LongWrapper w = JSON.std.beanFrom(LongWrapper.class, - a2q("{'value':2}")); - assertEquals(Long.valueOf(2L), w.value); - - w = JSON.std.beanFrom(LongWrapper.class, - a2q("{'value':null}")); - assertNull(w.value); - } - - // [jackson-jr#78], boolean/Boolean - - public void testBooleanPrimitive() throws Exception - { - BooleanPrimitiveWrapper w = JSON.std.beanFrom(BooleanPrimitiveWrapper.class, - a2q("{'value':true}")); - assertTrue(w.value); - - w = JSON.std.beanFrom(BooleanPrimitiveWrapper.class, - a2q("{'value':null}")); - assertFalse(w.value); - } - - public void testBooleanWrapper() throws Exception - { - BooleanWrapper w = JSON.std.beanFrom(BooleanWrapper.class, - a2q("{'value':true}")); - assertEquals(Boolean.TRUE, w.value); - - w = JSON.std.beanFrom(BooleanWrapper.class, - a2q("{'value':null}")); - assertNull(w.value); - } - - // [jackson-jr#78], boolean/Boolean - - public void testDoublePrimitive() throws Exception - { - DoublePrimitiveWrapper w = JSON.std.beanFrom(DoublePrimitiveWrapper.class, - a2q("{'value':0.25}")); - assertEquals(0.25, w.value); - - w = JSON.std.beanFrom(DoublePrimitiveWrapper.class, - a2q("{'value':null}")); - // yeah yeah, not kosher wrt epsilon etc but... - assertEquals(0.0, w.value); - } - - public void testDoubleWrapper() throws Exception - { - DoubleWrapper w = JSON.std.beanFrom(DoubleWrapper.class, - a2q("{'value':0.25}")); - assertEquals(Double.valueOf(0.25), w.value); - - w = JSON.std.beanFrom(DoubleWrapper.class, - a2q("{'value':null}")); - assertNull(w.value); - } -} diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadEnumMap21Test.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadEnumMap21Test.java index bb256a1c..d3db3c51 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadEnumMap21Test.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadEnumMap21Test.java @@ -29,7 +29,7 @@ public void testMapWithEnumKey() throws Exception WithEnumMap input = new WithEnumMap(DEF.E, "bar"); // verify serialization, should be ok: String json = JSON.std.asString(input); - assertEquals(aposToQuotes("{'values':{'E':'bar'}}"), json); + assertEquals(a2q("{'values':{'E':'bar'}}"), json); // and then get it back too WithEnumMap result = JSON.std.beanFrom(WithEnumMap.class, json); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadIntArray7Test.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadIntArray7Test.java new file mode 100644 index 00000000..e560c7d8 --- /dev/null +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadIntArray7Test.java @@ -0,0 +1,17 @@ +package com.fasterxml.jackson.jr.failing; + +import static org.junit.Assert.assertArrayEquals; + +import com.fasterxml.jackson.jr.ob.JSON; +import com.fasterxml.jackson.jr.ob.TestBase; + +public class ReadIntArray7Test extends TestBase +{ + public void testReadIntArray() throws Exception + { + final int[] input = new int[] { 1, 2, 3 }; + String json = JSON.std.asString(input); + int[] result = JSON.std.beanFrom(int[].class, json); + assertArrayEquals(input, result); + } +} diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/NullHandlingTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/NullHandlingTest.java index e6299900..b7c7ea8b 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/NullHandlingTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/NullHandlingTest.java @@ -13,6 +13,39 @@ static class StringBean { public String str = "a"; } + // [jackson-jr#78] + static class IntegerWrapper { + public Integer value; + } + static class IntPrimitiveWrapper { + public int value; + } + static class LongWrapper { + public Long value; + } + static class LongPrimitiveWrapper { + public long value; + } + static class FloatWrapper { + public Float value; + } + static class FloatPrimitiveWrapper { + public float value; + } + static class DoubleWrapper { + public Double value; + } + static class DoublePrimitiveWrapper { + public double value; + } + + static class BooleanWrapper { + public Boolean value; + } + static class BooleanPrimitiveWrapper { + public boolean value; + } + // Test to verify that outputting of nulls is configurable public void testMapNullEntries() throws Exception { @@ -42,4 +75,125 @@ public void testNullForByteArray() throws Exception Bean107 bean = JSON.std.beanFrom(Bean107.class, a2q("{'b':null}")); assertNull(bean.b); } + + // [jackson-jr#78], int/Integer + + public void testIntPrimitive() throws Exception + { + IntPrimitiveWrapper w = JSON.std.beanFrom(IntPrimitiveWrapper.class, + a2q("{'value':1}")); + assertEquals(1, w.value); + + w = JSON.std.beanFrom(IntPrimitiveWrapper.class, + a2q("{'value':null}")); + assertEquals(0, w.value); + } + + public void testIntWrapper() throws Exception + { + IntegerWrapper w = JSON.std.beanFrom(IntegerWrapper.class, + a2q("{'value':1}")); + assertEquals(Integer.valueOf(1), w.value); + + w = JSON.std.beanFrom(IntegerWrapper.class, + a2q("{'value':null}")); + assertNull(w.value); + } + + // [jackson-jr#78], long/Long + + public void testLongPrimitive() throws Exception + { + LongPrimitiveWrapper w = JSON.std.beanFrom(LongPrimitiveWrapper.class, + a2q("{'value':2}")); + assertEquals(2L, w.value); + + w = JSON.std.beanFrom(LongPrimitiveWrapper.class, + a2q("{'value':null}")); + assertEquals(0L, w.value); + } + + public void testLongWrapper() throws Exception + { + LongWrapper w = JSON.std.beanFrom(LongWrapper.class, + a2q("{'value':2}")); + assertEquals(Long.valueOf(2L), w.value); + + w = JSON.std.beanFrom(LongWrapper.class, + a2q("{'value':null}")); + assertNull(w.value); + } + + // [jackson-jr#78], float/Float + + public void testFloatPrimitive() throws Exception + { + FloatPrimitiveWrapper w = JSON.std.beanFrom(FloatPrimitiveWrapper.class, + a2q("{'value':0.25}")); + assertEquals(0.25f, w.value); + + w = JSON.std.beanFrom(FloatPrimitiveWrapper.class, + a2q("{'value':null}")); + assertEquals(0.0f, w.value); + } + + public void testFloatWrapper() throws Exception + { + FloatWrapper w = JSON.std.beanFrom(FloatWrapper.class, + a2q("{'value':0.25}")); + assertEquals(Float.valueOf(0.25f), w.value); + + w = JSON.std.beanFrom(FloatWrapper.class, + a2q("{'value':null}")); + assertNull(w.value); + } + + // [jackson-jr#78], double/Double + + public void testDoublePrimitive() throws Exception + { + DoublePrimitiveWrapper w = JSON.std.beanFrom(DoublePrimitiveWrapper.class, + a2q("{'value':0.25}")); + assertEquals(0.25, w.value); + + w = JSON.std.beanFrom(DoublePrimitiveWrapper.class, + a2q("{'value':null}")); + // yeah yeah, not kosher wrt epsilon etc but... + assertEquals(0.0, w.value); + } + + public void testDoubleWrapper() throws Exception + { + DoubleWrapper w = JSON.std.beanFrom(DoubleWrapper.class, + a2q("{'value':0.25}")); + assertEquals(Double.valueOf(0.25), w.value); + + w = JSON.std.beanFrom(DoubleWrapper.class, + a2q("{'value':null}")); + assertNull(w.value); + } + + // [jackson-jr#78], boolean/Boolean + + public void testBooleanPrimitive() throws Exception + { + BooleanPrimitiveWrapper w = JSON.std.beanFrom(BooleanPrimitiveWrapper.class, + a2q("{'value':true}")); + assertTrue(w.value); + + w = JSON.std.beanFrom(BooleanPrimitiveWrapper.class, + a2q("{'value':null}")); + assertFalse(w.value); + } + + public void testBooleanWrapper() throws Exception + { + BooleanWrapper w = JSON.std.beanFrom(BooleanWrapper.class, + a2q("{'value':true}")); + assertEquals(Boolean.TRUE, w.value); + + w = JSON.std.beanFrom(BooleanWrapper.class, + a2q("{'value':null}")); + assertNull(w.value); + } } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadBeansTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadBeansTest.java index 7be133e0..b96b8bcf 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadBeansTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadBeansTest.java @@ -70,7 +70,7 @@ static class URLBean { public void testSimpleBean() throws Exception { - final String INPUT = aposToQuotes("{'name':{'first':'Bob','last':'Burger'},'x':13, 'option': 'Option1'}"); + final String INPUT = a2q("{'name':{'first':'Bob','last':'Burger'},'x':13, 'option': 'Option1'}"); TestBean bean = JSON.std.beanFrom(TestBean.class, INPUT); assertNotNull(bean); @@ -83,7 +83,7 @@ public void testSimpleBean() throws Exception public void testSimpleBeanCaseInsensitive() throws Exception { - final String INPUT = aposToQuotes("{'NaMe':{'FIRST':'Bob','last':'Burger'},'x':13, 'optioN': 'opTIOn1'}"); + final String INPUT = a2q("{'NaMe':{'FIRST':'Bob','last':'Burger'},'x':13, 'optioN': 'opTIOn1'}"); TestBean bean = JSON.builder() .enable(JSON.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @@ -101,7 +101,7 @@ public void testSimpleBeanCaseInsensitive() throws Exception public void testUnknownProps() throws Exception { - final String INPUT = aposToQuotes("{'first':'Bob','middle':'Eugene', 'last':'Smith'}"); + final String INPUT = a2q("{'first':'Bob','middle':'Eugene', 'last':'Smith'}"); // First: fine if marked as such NameBean name = JSON.std @@ -125,7 +125,7 @@ public void testUnknownProps() throws Exception public void testPOJOWithList() throws Exception { - final String INPUT = aposToQuotes("{'names': [ { 'first':'John','last':'Smith' }," + final String INPUT = a2q("{'names': [ { 'first':'John','last':'Smith' }," +"{'first':'Bob','last':'Burger' } ] }"); NameListBean list = JSON.std.beanFrom(NameListBean.class, INPUT); assertNotNull(list); @@ -137,7 +137,7 @@ public void testPOJOWithList() throws Exception public void testPOJOWithMap() throws Exception { - final String INPUT = aposToQuotes("{'stuff': { 'a':3, 'b':4 } }"); + final String INPUT = a2q("{'stuff': { 'a':3, 'b':4 } }"); MapBean map = JSON.std.beanFrom(MapBean.class, INPUT); assertNotNull(map); assertNotNull(map.stuff); @@ -147,7 +147,7 @@ public void testPOJOWithMap() throws Exception public void testSimpleBeanCollections() throws Exception { - final String INPUT = aposToQuotes("[" + final String INPUT = a2q("[" +"{'name':{'first':'Bob','last':'Burger'},'x':13}" +",{'x':-145,'name':{'first':'Billy','last':'Bacon'}}" +"]"); @@ -182,7 +182,7 @@ private void _verifySimpleBeanCollections(List beans) { // @since 2.10 public void testSimpleBeanMaps() throws Exception { - final String INPUT = aposToQuotes("{ 'first':" + final String INPUT = a2q("{ 'first':" +"{'name':{'first':'Bob','last':'Burger'},'x':13}" +", 'second':{'x':-145,'name':{'first':'Billy','last':'Bacon'}}" +"}"); @@ -277,7 +277,7 @@ public void testNameWithLeadingUppers() throws Exception final String expURL = "http://foo"; URLBean bean = JSON.std .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) - .beanFrom(URLBean.class, aposToQuotes("{'URL':'"+expURL+"'}")); + .beanFrom(URLBean.class, a2q("{'URL':'"+expURL+"'}")); assertEquals(expURL, bean.url); } } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadFeaturesTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadFeaturesTest.java index 52a1c06b..7923cd15 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadFeaturesTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadFeaturesTest.java @@ -22,26 +22,26 @@ public void testPojoWithIsGetter() throws Exception json = JSON.std.asString(new IsBean()); // by default, will use 'is-getter': - assertEquals(aposToQuotes("{'enabled':true,'value':42}"), json); + assertEquals(a2q("{'enabled':true,'value':42}"), json); // but can disable json = JSON.std .without(JSON.Feature.USE_IS_GETTERS) .asString(new IsBean()); - assertEquals(aposToQuotes("{'value':42}"), json); + assertEquals(a2q("{'value':42}"), json); // .... as well as using alternative json = JSON.builder() .disable(JSON.Feature.USE_IS_GETTERS) .build() .asString(new IsBean()); - assertEquals(aposToQuotes("{'value':42}"), json); + assertEquals(a2q("{'value':42}"), json); // and go back as well json = JSON.std .with(JSON.Feature.USE_IS_GETTERS) .asString(new IsBean()); - assertEquals(aposToQuotes("{'enabled':true,'value':42}"), json); + assertEquals(a2q("{'enabled':true,'value':42}"), json); } public void testFailOnDupMapKeys() throws Exception diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadListTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadListTest.java index dc2b39b6..ac13e8bc 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadListTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadListTest.java @@ -85,7 +85,7 @@ public void testListOfMaps() throws Exception .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .with(JSON.Feature.USE_FIELDS) .beanFrom(ListHolder.class, - aposToQuotes("{'stuff':[{'a':4}, {'a':6}]}")); + a2q("{'stuff':[{'a':4}, {'a':6}]}")); List> list = h.stuff; assertNotNull(list); assertEquals(2, list.size()); @@ -99,7 +99,7 @@ public void testInvalidListOfMaps() throws Exception .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .with(JSON.Feature.USE_FIELDS) .beanFrom(ListHolder.class, - aposToQuotes("{'stuff':{ 'a' : 3 }}")); + a2q("{'stuff':{ 'a' : 3 }}")); } catch (JSONObjectException e) { verifyException(e, "Unexpected token START_OBJECT"); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadMapTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadMapTest.java index 321a62ee..66f8a0bb 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadMapTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadMapTest.java @@ -55,7 +55,7 @@ public Map build() { public void testMapOfLists() throws Exception { - final String INPUT = aposToQuotes("{'stuff':{'a':[1, 2, 3], 'b' : [7, 2]}}"); + final String INPUT = a2q("{'stuff':{'a':[1, 2, 3], 'b' : [7, 2]}}"); final JSON j = JSON.std .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .with(JSON.Feature.USE_FIELDS); @@ -82,7 +82,7 @@ public void testInvalidMapOfLists() throws Exception .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .with(JSON.Feature.USE_FIELDS) .beanFrom(MapHolder.class, - aposToQuotes("{'stuff':[ 1 ]}")); + a2q("{'stuff':[ 1 ]}")); } catch (JSONObjectException e) { verifyException(e, "Unexpected token START_ARRAY"); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSequencesTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSequencesTest.java index 1933b091..71501d01 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSequencesTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSequencesTest.java @@ -21,7 +21,7 @@ static class Bean { public void testAnySequence() throws Exception { - final String INPUT = aposToQuotes("'hello world!' 127 true [ 1, 2, 3]\nnull { 'msg':'none'} "); + final String INPUT = a2q("'hello world!' 127 true [ 1, 2, 3]\nnull { 'msg':'none'} "); // First, managed ValueIterator it = JSON.std.anySequenceFrom(INPUT); @@ -104,7 +104,7 @@ private void _verifyAnySequence(ValueIterator it) throws Exception public void testBeanSequence() throws Exception { - final String INPUT = aposToQuotes("{'id':1, 'msg':'foo'} {'id':2, 'msg':'Same'} null "); + final String INPUT = a2q("{'id':1, 'msg':'foo'} {'id':2, 'msg':'Same'} null "); // First, managed ValueIterator it = JSON.std.beanSequenceFrom(Bean.class, INPUT); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSimpleTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSimpleTest.java index 02fe6997..caf67959 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSimpleTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadSimpleTest.java @@ -5,6 +5,8 @@ import java.io.File; import java.net.URI; import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import com.fasterxml.jackson.core.JsonParser; @@ -36,12 +38,12 @@ static class DateWrapper { */ public void testByteArray() throws Exception { - byte[] result = JSON.std.beanFrom(byte[].class, quote("YWJj")); + byte[] result = JSON.std.beanFrom(byte[].class, q("YWJj")); assertEquals("abc", new String(result, "UTF-8")); } public void testCharArray() throws Exception { - char[] result = JSON.std.beanFrom(char[].class, quote("abc")); + char[] result = JSON.std.beanFrom(char[].class, q("abc")); assertEquals("abc", new String(result)); } @@ -174,9 +176,20 @@ public void testBooleanFail() throws Exception { public void testMiscScalars() throws Exception { assertEquals(new Date(123456L), JSON.std.beanFrom(Date.class,"123456")); - assertEquals(Object.class, JSON.std.beanFrom(Class.class, quote(Object.class.getName()))); + assertEquals(Object.class, JSON.std.beanFrom(Class.class, q(Object.class.getName()))); } + public void testMiscUriTypes() throws Exception + { + final String URL_STR = "http://fasterxml.com"; + final URL url = new URL(URL_STR); + assertEquals(url, JSON.std.beanFrom(URL.class, q(URL_STR))); + + Path p = Paths.get(new URI("file:///foo/bar.txt")); + assertEquals(p, + JSON.std.beanFrom(Path.class, q("file:///foo/bar.txt"))); + } + public void testMiscScalarFail() throws Exception { for (String input : new String[] { " false ", "true", "[ ]", "{ }" } ) { try { @@ -220,13 +233,13 @@ public void testNullForMiscScalars() throws Exception { // Testing that `null` will not cause an exception, for now at least public void testNullForPrimitiveProperties() throws Exception { - BooleanWrapper w = JSON.std.beanFrom(BooleanWrapper.class, aposToQuotes("{'value':null}")); + BooleanWrapper w = JSON.std.beanFrom(BooleanWrapper.class, a2q("{'value':null}")); assertNotNull(w); assertFalse(w.value); } public void testNullForScalarProperties() throws Exception { - DateWrapper w = JSON.std.beanFrom(DateWrapper.class, aposToQuotes("{'value':null}")); + DateWrapper w = JSON.std.beanFrom(DateWrapper.class, a2q("{'value':null}")); assertNotNull(w); assertNull(w.value); } @@ -264,7 +277,7 @@ public void testSimpleEnums() throws Exception assertEquals(ABC.B, abc); // then from name - abc = JSON.std.beanFrom(ABC.class, quote("C")); + abc = JSON.std.beanFrom(ABC.class, q("C")); assertEquals(ABC.C, abc); // `null`s ok too @@ -303,7 +316,7 @@ public void testTreeReadWithoutCodec() throws Exception } try { - JSON.std.beanFrom(TreeNode.class, quote("abc")); + JSON.std.beanFrom(TreeNode.class, q("abc")); fail("Should not pass"); } catch (JSONObjectException e) { verifyException(e, "No `TreeCodec` specified"); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtorsTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtorsTest.java index 7419e6ca..46ed2479 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtorsTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtorsTest.java @@ -25,7 +25,7 @@ static class FromLong2 { public void testStringCtor() throws Exception { - FromString output = JSON.std.beanFrom(FromString.class, quote("abc")); + FromString output = JSON.std.beanFrom(FromString.class, q("abc")); assertNotNull(output); assertEquals("abc", output.value); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleComposerTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleComposerTest.java index 79896694..db0fc816 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleComposerTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleComposerTest.java @@ -124,7 +124,7 @@ public void testComposerWithPojo() throws Exception .end() .end() .finish(); - assertEquals(aposToQuotes("[{'first':'Bob'},{'name':{'first':'Bill'}}]"), json); + assertEquals(a2q("[{'first':'Bob'},{'name':{'first':'Bill'}}]"), json); } public void testComposerWithIndent() throws Exception @@ -136,7 +136,7 @@ public void testComposerWithIndent() throws Exception .put("name", "Bill") .end() .finish(); - assertEquals(aposToQuotes("{\n" + assertEquals(a2q("{\n" +" 'name' : 'Bill'\n" +"}"), json); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleFieldTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleFieldTest.java index d0d33ba1..70b40fcd 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleFieldTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/SimpleFieldTest.java @@ -25,20 +25,20 @@ public void testSerializeWithoutField() throws Exception { String json = JSON.std.without(JSON.Feature.USE_FIELDS) .asString(new XY(1, 2)); - assertEquals(aposToQuotes("{'y':2}"), json); + assertEquals(a2q("{'y':2}"), json); } public void testSerializeWithField() throws Exception { String json = JSON.std.with(JSON.Feature.USE_FIELDS) .asString(new XY(1, 2)); - assertEquals(aposToQuotes("{'x':1,'y':2}"), json); + assertEquals(a2q("{'x':1,'y':2}"), json); } public void testDeserializeWithField() throws Exception { XY result = JSON.std.with(JSON.Feature.USE_FIELDS) - .beanFrom(XY.class, aposToQuotes("{'x':3,'y':4}")); + .beanFrom(XY.class, a2q("{'x':3,'y':4}")); assertEquals(4, result.getY()); assertEquals(3, result.x); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/TestBase.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/TestBase.java index 1dc56447..2ba6cf1c 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/TestBase.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/TestBase.java @@ -52,16 +52,12 @@ protected JsonParser parserFor(JSON json, String source) throws IOException { return json.getStreamingFactory().createParser(source.toCharArray()); } - protected String quote(String str) { + protected String q(String str) { return "\"" + str + "\""; } protected String a2q(String json) { - return aposToQuotes(json); - } - - protected String aposToQuotes(String json) { - return json.replace("'", "\""); + return json.replace('\'', '"'); } protected JSON jsonWithModifier(final ReaderWriterModifier modifier) { diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteBeansTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteBeansTest.java index acc82987..293b2c70 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteBeansTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteBeansTest.java @@ -55,6 +55,24 @@ public StringBeanBean(StringBean b) { bean = b; } } + + static class TreeNodeBean { + public int id; + public String name; + + public TreeNodeBean nextLeft, nextRight; + + public TreeNodeBean(int id, String name) { + this.id = id; + this.name = name; + } + } + + /* + /********************************************************************** + /* Test methods + /********************************************************************** + */ public void testBinary() throws Exception { @@ -105,7 +123,7 @@ public void testMethodsFromSuperclass() throws Exception } BaseImpl result = JSON.std.beanFrom(BaseImpl.class, - aposToQuotes("{ 'extra':5, 'value':-245 }")); + a2q("{ 'extra':5, 'value':-245 }")); assertEquals(5, result.getExtra()); assertEquals(-245, result.getValue()); } @@ -128,4 +146,19 @@ public void testBeanNulls() throws Exception assertEquals(a2q("{'bean':{'value':null}}"), withNulls.asString(new StringBeanBean(new StringBean(null)))); } + + public void testBeanWithRecursiveType() throws Exception + { + TreeNodeBean root = new TreeNodeBean(1, "root"); + TreeNodeBean left = new TreeNodeBean(2, "left"); + TreeNodeBean right = new TreeNodeBean(3, "right"); + root.nextLeft = left; + root.nextRight = right; + + assertEquals(a2q("{'id':1,'name':'root'," + +"'nextLeft':{'id':2,'name':'left'}," + +"'nextRight':{'id':3,'name':'right'}" + +"}"), + JSON.std.asString(root)); + } } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteSimpleTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteSimpleTest.java index b255d784..9e575cae 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteSimpleTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/WriteSimpleTest.java @@ -5,6 +5,8 @@ import java.io.StringWriter; import java.net.URI; import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON.Feature; @@ -81,7 +83,7 @@ public void testSimpleBooleanArray() throws Exception { } public void testSimpleStringArray() throws Exception { - assertEquals(aposToQuotes("['abc','def']"), JSON.std.asString(new String[] { "abc", "def" })); + assertEquals(a2q("['abc','def']"), JSON.std.asString(new String[] { "abc", "def" })); } public void testNest() throws Exception @@ -103,13 +105,16 @@ public void testNest() throws Exception public void testKnownSimpleTypes() throws Exception { final String URL_STR = "http://fasterxml.com"; - assertEquals(quote(URL_STR), - JSON.std.asString(new URI(URL_STR))); + final URI uri = new URI(URL_STR); + assertEquals(q(URL_STR), JSON.std.asString(uri)); final String PATH = "/foo/bar.txt"; - assertEquals(quote(PATH), + assertEquals(q(PATH), JSON.std.asString(new File(PATH))); - assertEquals(quote("B"), JSON.std.asString(ABC.B)); + Path p = Paths.get(new URI("file:///foo/bar.txt")); + assertEquals(q("file:///foo/bar.txt"), JSON.std.asString(p)); + + assertEquals(q("B"), JSON.std.asString(ABC.B)); assertEquals("1", JSON.std.with(Feature.WRITE_ENUMS_USING_INDEX).asString(ABC.B)); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueReadersTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueReadersTest.java index 0ab98621..dcb06f87 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueReadersTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueReadersTest.java @@ -198,7 +198,7 @@ public void testCustomBeanReader() throws Exception // similarly with wrapper CustomValueBean bean = json.beanFrom(CustomValueBean.class, - aposToQuotes("{ 'custom' : 137 }")); + a2q("{ 'custom' : 137 }")); assertEquals(138, bean.custom.value); // but also ensure we can change registered handler(s) @@ -224,7 +224,7 @@ public void testCustomEnumReader() throws Exception { // First: without handler, will fail to map try { - JSON.std.beanFrom(ABC.class, quote("n/a")); + JSON.std.beanFrom(ABC.class, q("n/a")); fail("Should not pass"); } catch (JSONObjectException e) { verifyException(e, "Failed to find Enum of type"); @@ -232,13 +232,13 @@ public void testCustomEnumReader() throws Exception // then with custom, should be fine JSON json = jsonWithProvider(new CustomReaders(0)); - ABC v = json.beanFrom(ABC.class, quote("n/a")); + ABC v = json.beanFrom(ABC.class, q("n/a")); assertEquals(ABC.DEF, v); // but if we remove, again error JSON json2 = jsonWithProvider((ReaderWriterProvider) null); try { - json2.beanFrom(ABC.class, quote("n/a")); + json2.beanFrom(ABC.class, q("n/a")); fail("Should not pass"); } catch (JSONObjectException e) { verifyException(e, "Failed to find Enum of type"); @@ -249,31 +249,31 @@ public void testCustomEnumReader() throws Exception public void testCustomStringReader() throws Exception { String allCaps = jsonWithProvider(new CapStringReaderProvider()) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("SOME TEXT", allCaps); } public void testChainedStringReaders() throws Exception { String result = jsonWithProviders(new CapStringReaderProvider(), new OverrideStringReaderProvider("foo")) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("SOME TEXT", result); result = jsonWithProviders(new NoOpProvider(), new OverrideStringReaderProvider("foo")) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("foo", result); // and ok not to have anything, too result = jsonWithProviders(new NoOpProvider(), new NoOpProvider()) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("Some text", result); // Plus nulls fine too result = jsonWithProviders(null, new OverrideStringReaderProvider("foo")) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("foo", result); result = jsonWithProviders(new OverrideStringReaderProvider("foo"), null) - .beanFrom(String.class, quote("Some text")); + .beanFrom(String.class, q("Some text")); assertEquals("foo", result); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueWritersTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueWritersTest.java index 60448d72..9998d9c2 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueWritersTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/CustomValueWritersTest.java @@ -85,7 +85,7 @@ public void testCustomBeanWriter() throws Exception assertEquals("{\"wrapped\":{}}", JSON.std.asString(new CustomBeanWrapper())); final JSON withCustom = jsonWithProvider(new CustomWriters()); - assertEquals(quote("xxx"), withCustom.asString(new CustomBean())); + assertEquals(q("xxx"), withCustom.asString(new CustomBean())); assertEquals("{\"wrapped\":\"xxx\"}", withCustom.asString(new CustomBeanWrapper())); assertEquals("[\"xxx\"]", withCustom.asString(new CustomBean[] { new CustomBean() })); assertEquals("{\"value\":\"xxx\"}", @@ -100,18 +100,18 @@ public void testCustomBeanWriter() throws Exception public void testChainedBeanWriters() throws Exception { - assertEquals(quote("abc"), + assertEquals(q("abc"), jsonWithProviders(new CustomWriters("abc"), new CustomWriters("def")) .asString(new CustomBean())); - assertEquals(quote("def"), + assertEquals(q("def"), jsonWithProviders(new BogusProvider(), new CustomWriters("def")) .asString(new CustomBean())); // as well as passing `null` - assertEquals(quote("xxx"), + assertEquals(q("xxx"), jsonWithProviders(null, new CustomWriters("xxx")) .asString(new CustomBean())); - assertEquals(quote("yyy"), + assertEquals(q("yyy"), jsonWithProviders(new CustomWriters("yyy"), null) .asString(new CustomBean())); } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/POJODefinitionOverrideTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/POJODefinitionOverrideTest.java index b44ee05c..75688000 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/POJODefinitionOverrideTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/POJODefinitionOverrideTest.java @@ -48,7 +48,7 @@ static class NoOpModifier extends ReaderWriterModifier { } public void testReadIgnoreProperty() throws Exception { // verify default read first - final String INPUT = aposToQuotes("{'first':'Bob','last':'Burger'}"); + final String INPUT = a2q("{'first':'Bob','last':'Burger'}"); NameBean bean = JSON.std.beanFrom(NameBean.class, INPUT); assertEquals("Bob", bean.getFirst()); assertEquals("Burger", bean.getLast()); @@ -67,7 +67,7 @@ public void testReadIgnoreProperty() throws Exception public void testModifierPairForReading() throws Exception { - final String INPUT = aposToQuotes("{'first':'Bob','last':'Burger'}"); + final String INPUT = a2q("{'first':'Bob','last':'Burger'}"); NameBean bean = jsonWithModifiers(new NoOpModifier(), new MyPropertyModifier("last")) .beanFrom(NameBean.class, INPUT); assertEquals("Bob", bean.getFirst()); @@ -84,14 +84,14 @@ public void testWriteInReverseOrder() throws Exception { // verify default write first final NameBean input = new NameBean("Bob", "Burger"); - final String EXP_DEFAULT = aposToQuotes("{'first':'Bob','last':'Burger'}"); + final String EXP_DEFAULT = a2q("{'first':'Bob','last':'Burger'}"); assertEquals(EXP_DEFAULT, JSON.std.asString(input)); // but then use customized POJO introspection String json = jsonWithModifier(new MyPropertyModifier("xxx")) .asString(input); - assertEquals(aposToQuotes("{'last':'Burger','first':'Bob'}"), json); + assertEquals(a2q("{'last':'Burger','first':'Bob'}"), json); // and last, to ensure no leakage of customizations assertEquals(EXP_DEFAULT, JSON.std.asString(input)); @@ -103,11 +103,11 @@ public void testModifierPairForWriting() throws Exception String json = jsonWithModifiers(new NoOpModifier(), new MyPropertyModifier("xxx")) .asString(input); - assertEquals(aposToQuotes("{'last':'Burger','first':'Bill'}"), json); + assertEquals(a2q("{'last':'Burger','first':'Bill'}"), json); // and nulls fine too wrt chaining json = jsonWithModifiers(null, new MyPropertyModifier("xxx")) .asString(input); - assertEquals(aposToQuotes("{'last':'Burger','first':'Bill'}"), json); + assertEquals(a2q("{'last':'Burger','first':'Bill'}"), json); } } diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderModifierTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderModifierTest.java index f537fa3e..98369568 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderModifierTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderModifierTest.java @@ -69,7 +69,7 @@ public ValueReader modifyValueReader(JSONReader readContext, public void testStringReaderReplacement() throws Exception { - final String input = quote("foobar"); + final String input = q("foobar"); assertEquals("foobar", JSON.std.beanFrom(String.class, input)); // but then with modifier @@ -98,7 +98,7 @@ public Object read(JSONReader reader, JsonParser p) throws IOException { String.valueOf(map.get("last")).toUpperCase()); }; }); - final String input = aposToQuotes("{'first':'foo', 'last':'bar'}"); + final String input = a2q("{'first':'foo', 'last':'bar'}"); NameBean result = jsonWithModifier(mod).beanFrom(NameBean.class, input); assertEquals("FOO", result.getFirst()); assertEquals("BAR", result.getLast()); @@ -111,7 +111,7 @@ public Object read(JSONReader reader, JsonParser p) throws IOException { public void testPOJOReaderDelegation() throws Exception { - final String input = aposToQuotes("{'first':'Foo', 'last':'Bar'}"); + final String input = a2q("{'first':'Foo', 'last':'Bar'}"); NameBean result = jsonWithModifier(new LowerCasingReaderModifier()) .beanFrom(NameBean.class, input); assertEquals("foo", result.getFirst()); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocatorTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocatorTest.java index 0a73b116..68b1f6e7 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocatorTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocatorTest.java @@ -54,9 +54,15 @@ public void testBasicTypeDetectionForSer() { assertEquals(ValueWriterLocator.SER_COLLECTION, td.findSerializationType(LinkedHashSet.class)); assertEquals(ValueWriterLocator.SER_LIST, td.findSerializationType(ArrayList.class)); - assertEquals(ValueWriterLocator.SER_NUMBER_INTEGER, td.findSerializationType(Integer.class)); assertEquals(ValueWriterLocator.SER_NUMBER_INTEGER, td.findSerializationType(Integer.TYPE)); + assertEquals(ValueWriterLocator.SER_NUMBER_INTEGER_WRAPPER, td.findSerializationType(Integer.class)); + + assertEquals(ValueWriterLocator.SER_NUMBER_LONG, td.findSerializationType(Long.TYPE)); + assertEquals(ValueWriterLocator.SER_NUMBER_LONG_WRAPPER, td.findSerializationType(Long.class)); + assertEquals(ValueWriterLocator.SER_NUMBER_DOUBLE, td.findSerializationType(Double.TYPE)); + assertEquals(ValueWriterLocator.SER_NUMBER_DOUBLE_WRAPPER, td.findSerializationType(Double.class)); + // more specific types assertEquals(ValueWriterLocator.SER_CALENDAR, td.findSerializationType(Calendar.class)); assertEquals(ValueWriterLocator.SER_CALENDAR, td.findSerializationType(GregorianCalendar.class)); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifier112Test.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifier112Test.java new file mode 100644 index 00000000..6583fddd --- /dev/null +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifier112Test.java @@ -0,0 +1,97 @@ +package com.fasterxml.jackson.jr.ob.impl; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.fasterxml.jackson.core.JsonGenerator; + +import com.fasterxml.jackson.jr.ob.*; +import com.fasterxml.jackson.jr.ob.api.*; + +public class ValueWriterModifier112Test extends TestBase +{ + static class TestBean112 { + public Path p1; + public Path p2; + } + + static class StringBean112 { + public String s1; + public String s2; + public String s3; + } + + static class PathWriter implements ValueWriter { + @Override + public void writeValue(JSONWriter context, JsonGenerator g, Object value) throws IOException { + g.writeString(((Path) value).toString().replace(File.separatorChar, '/')); + } + + @Override + public Class valueType() { + return Path.class; + } + } + + static class UpperCaseWriter implements ValueWriter { + @Override + public void writeValue(JSONWriter context, JsonGenerator g, Object value) throws IOException { + g.writeString(String.valueOf(value).toUpperCase()); + } + + @Override + public Class valueType() { + return String.class; + } + } + + private final JSON WRITER = JSON.builder() + .register(new JacksonJrExtension() { + @Override + protected void register(ExtensionContext ctxt) { + ctxt.insertModifier(new ReaderWriterModifier() { + @Override + public ValueWriter overrideStandardValueWriter(JSONWriter writeContext, Class type, int stdTypeId) { + if (Path.class.isAssignableFrom(type)) { + return new PathWriter(); + } + if (type == String.class) { + return new UpperCaseWriter(); + } + return null; + } + }); + ctxt.insertProvider(new ReaderWriterProvider() { + @Override + public ValueWriter findValueWriter(JSONWriter writeContext, Class type) { + if (Path.class.isAssignableFrom(type)) { + return new PathWriter(); + } + return null; + } + }); + } + }).build(); + + // [jackson-jr#112] + public void testMultipleFieldOverrides() throws Exception + { + TestBean112 input = new TestBean112(); + input.p1 = Paths.get("some/path"); + input.p2 = Paths.get("some/other/path"); + String json = WRITER.asString(input); + assertEquals(a2q("{'p1':'some/path','p2':'some/other/path'}"), json); + } + + public void testMultipleStringFieldOverrides() throws Exception + { + StringBean112 input = new StringBean112(); + input.s1 = "abc"; + input.s2 = "def"; + input.s3 = "g"; + String json = WRITER.asString(input); + assertEquals(a2q("{'s1':'ABC','s2':'DEF','s3':'G'}"), json); + } +} diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifierTest.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifierTest.java index 5fdf90ba..d8198899 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifierTest.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterModifierTest.java @@ -74,6 +74,15 @@ public ValueWriter modifyValueWriter(JSONWriter writeContext, } } + static class Name { + public String first, last; + + public Name(String f, String l) { + first = f; + last = l; + } + } + /* /********************************************************************** /* Tests for wholesale replacement of `ValueReader` @@ -96,10 +105,19 @@ public Class valueType() { } }); final String input = "foobar"; - String result = jsonWithModifier(mod).asString(input); - assertEquals(quote("FOOBAR"), result); + final JSON jsonWithMod = jsonWithModifier(mod); + String result = jsonWithMod.asString(input); + assertEquals(q("FOOBAR"), result); // but also verify that no caching occurs wrt global standard variant: - assertEquals(quote("foobar"), JSON.std.asString(input)); + assertEquals(q("foobar"), JSON.std.asString(input)); + + // And then also applicable for multiple POJO properties + assertEquals(a2q("{'first':'BOB','last':'HOPE'}"), + jsonWithMod.asString(new Name("Bob", "Hope"))); + + // .. and not global standard variant + assertEquals(a2q("{'first':'Bob','last':'Hope'}"), + JSON.std.asString(new Name("Bob", "Hope"))); } public void testPOJOWriterReplacement() throws Exception @@ -120,9 +138,9 @@ public Class valueType() { }); final NameBean input = new NameBean("Foo", "Bar"); String json = jsonWithModifier(mod).asString(input); - assertEquals(quote("Foo-Bar"), json); + assertEquals(q("Foo-Bar"), json); // but also verify that no caching occurs wrt global standard variant: - assertEquals(aposToQuotes("{'first':'Foo','last':'Bar'}"), + assertEquals(a2q("{'first':'Foo','last':'Bar'}"), JSON.std.asString(input)); } @@ -131,10 +149,10 @@ public void testPOJOWriterDelegatingReplacement() throws Exception final NameBean input = new NameBean("Foo", "Bar"); String json = jsonWithModifier(new ArrayingWriterModifier()) .asString(input); - assertEquals(aposToQuotes("[{'first':'Foo','last':'Bar'}]"), json); + assertEquals(a2q("[{'first':'Foo','last':'Bar'}]"), json); // but also verify that no caching occurs wrt global standard variant: - assertEquals(aposToQuotes("{'first':'Foo','last':'Bar'}"), + assertEquals(a2q("{'first':'Foo','last':'Bar'}"), JSON.std.asString(input)); } } diff --git a/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2/JacksonJrRequestBodyConverter.java b/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2/JacksonJrRequestBodyConverter.java index e0cdf1b5..04818131 100644 --- a/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2/JacksonJrRequestBodyConverter.java +++ b/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2/JacksonJrRequestBodyConverter.java @@ -9,9 +9,6 @@ import com.fasterxml.jackson.jr.ob.JSON; -/** - * Created by Gulajava Ministudio on 11/18/15. - */ public class JacksonJrRequestBodyConverter implements Converter { private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); diff --git a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JacksonJrsTreeCodec.java b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JacksonJrsTreeCodec.java index d4316456..070f39df 100644 --- a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JacksonJrsTreeCodec.java +++ b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JacksonJrsTreeCodec.java @@ -59,7 +59,7 @@ private JrsValue nodeFrom(JsonParser p) throws IOException { Map values = _map(); while (p.nextToken() != JsonToken.END_OBJECT) { - final String currentName = p.getCurrentName(); + final String currentName = p.currentName(); p.nextToken(); values.put(currentName, nodeFrom(p)); } diff --git a/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/SimpleTraverseTest.java b/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/SimpleTraverseTest.java index 700f3720..15d34643 100644 --- a/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/SimpleTraverseTest.java +++ b/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/SimpleTraverseTest.java @@ -14,7 +14,7 @@ public void testSimpleObject() throws Exception assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); - assertEquals("a", p.getCurrentName()); + assertEquals("a", p.currentName()); assertToken(JsonToken.START_ARRAY, p.nextToken()); @@ -25,7 +25,7 @@ public void testSimpleObject() throws Exception assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); - assertEquals("b", p.getCurrentName()); + assertEquals("b", p.currentName()); assertToken(JsonToken.VALUE_TRUE, p.nextToken()); assertToken(JsonToken.END_OBJECT, p.nextToken()); @@ -34,12 +34,12 @@ public void testSimpleObject() throws Exception assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); - assertEquals("c", p.getCurrentName()); + assertEquals("c", p.currentName()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(-2, p.getIntValue()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); - assertEquals("d", p.getCurrentName()); + assertEquals("d", p.currentName()); assertToken(JsonToken.VALUE_NULL, p.nextToken()); assertToken(JsonToken.END_OBJECT, p.nextToken()); diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 266be02a..67db91bb 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -33,3 +33,9 @@ Reed Passaretti (@reed53) * Reported #107: Cannot deserialize `byte[]` from JSON `null` value (2.15.3) + +Julian Honnen (@jhonnen) + +* Reported #112: `overrideStandardValueWriter` only applied to first `java.nio.file.Path` + valued field of bean + (2.17.0) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 79d7b650..5873c6db 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -13,7 +13,12 @@ Modules: 2.17.0 (not yet released) -- +#78: Deserializes "null" to "0.0" for `java.lang.Double` (wrapper) + (reported by @bill-phast) +#112: `overrideStandardValueWriter` only applied to first `java.nio.file.Path` + valued field of bean + (reported by Julian H) +#116: Add read/write support for `java.nio.file.Path` 2.16.1 (24-Dec-2023) @@ -24,6 +29,10 @@ No changes since 2.16.0 * Upgrade `retrofit` dependency to 2.9.0 (from 2.7.2) * Upgrade `okhttp` dependency (of retrofit) to 4.11.0 (from 3.14.9) +2.15.4 + +No changes since 2.15.3 + 2.15.3 (12-Oct-2023) #107: Cannot deserialize `byte[]` from JSON `null` value @@ -39,7 +48,6 @@ No changes since 2.14 #102: Missing module-info dependency from `jackson-jr-annotation-support` #103: Some artifacts missing `NOTICE`, `LICENSE` files -- Java/JDK baseline raised to Java 8 2.14.2 (28-Jan-2023) 2.14.1 (21-Nov-2022)