From eec46f37e83b402ad75570cdf0f12111cc05be53 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 23 Feb 2024 15:53:09 -0800 Subject: [PATCH 1/5] Implement #25: add support for single-int Constructors --- .../AnnotationBasedIntrospector.java | 19 ++--- .../jackson/jr/ob/impl/BeanConstructors.java | 69 +++++++++++++++++++ .../jr/ob/impl/BeanPropertyIntrospector.java | 12 ++-- .../jackson/jr/ob/impl/BeanReader.java | 59 +++++++--------- .../jackson/jr/ob/impl/POJODefinition.java | 38 +++++++--- .../jr/ob/impl/ValueReaderLocator.java | 17 +---- release-notes/VERSION-2.x | 1 + 7 files changed, 141 insertions(+), 74 deletions(-) create mode 100644 jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java diff --git a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java index 4047b9c0..246e9de6 100644 --- a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java +++ b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.jr.ob.JSON; +import com.fasterxml.jackson.jr.ob.impl.BeanConstructors; import com.fasterxml.jackson.jr.ob.impl.JSONReader; import com.fasterxml.jackson.jr.ob.impl.JSONWriter; import com.fasterxml.jackson.jr.ob.impl.POJODefinition; @@ -82,31 +83,31 @@ protected POJODefinition introspectDefinition() _findFields(); _findMethods(); - Constructor defaultCtor = null; - Constructor stringCtor = null; - Constructor longCtor = null; + BeanConstructors constructors = null; // A few things only matter during deserialization: constructors, // secondary ignoral information: - if (!_forSerialization) { + if (_forSerialization) { + constructors = null; + } else { + constructors = new BeanConstructors(_type); for (Constructor ctor : _type.getDeclaredConstructors()) { Class[] argTypes = ctor.getParameterTypes(); if (argTypes.length == 0) { - defaultCtor = ctor; + constructors.addNoArgsConstructor(ctor); } else if (argTypes.length == 1) { Class argType = argTypes[0]; if (argType == String.class) { - stringCtor = ctor; + constructors.addStringConstructor(ctor); } else if (argType == Long.class || argType == Long.TYPE) { - longCtor = ctor; + constructors.addLongConstructor(ctor); } } } } POJODefinition def = new POJODefinition(_type, - _pruneProperties(_forSerialization), - defaultCtor, stringCtor, longCtor); + _pruneProperties(_forSerialization), constructors); if (_ignorableNames != null) { def = def.withIgnorals(_ignorableNames); } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java new file mode 100644 index 00000000..0bd6def1 --- /dev/null +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java @@ -0,0 +1,69 @@ +package com.fasterxml.jackson.jr.ob.impl; + +import java.lang.reflect.Constructor; + +/** + * Container class added in 2.17 to encapsulate collection and use + * of various Constructors for User-defined (non-JDK) types (aka + * "Beans"). + */ +public class BeanConstructors +{ + protected final Class _valueType; + + protected Constructor _noArgsCtor; + protected Constructor _stringCtor; + protected Constructor _longCtor; + + public BeanConstructors(Class valueType) { + _valueType = valueType; + } + + public BeanConstructors addNoArgsConstructor(Constructor ctor) { + _noArgsCtor = ctor; + return this; + } + + public BeanConstructors addStringConstructor(Constructor ctor) { + _stringCtor = ctor; + return this; + } + + public BeanConstructors addLongConstructor(Constructor ctor) { + _longCtor = ctor; + return this; + } + + public void forceAccess() { + if (_noArgsCtor != null) { + _noArgsCtor.setAccessible(true); + } + if (_stringCtor != null) { + _stringCtor.setAccessible(true); + } + if (_longCtor != null) { + _longCtor.setAccessible(true); + } + } + + protected Object create() throws Exception { + if (_noArgsCtor == null) { + throw new IllegalStateException("Class "+_valueType.getName()+" does not have default constructor to use"); + } + return _noArgsCtor.newInstance((Object[]) null); + } + + protected Object create(String str) throws Exception { + if (_stringCtor == null) { + throw new IllegalStateException("Class "+_valueType.getName()+" does not have single-String constructor to use"); + } + return _stringCtor.newInstance(str); + } + + protected Object create(long l) throws Exception { + if (_longCtor == null) { + throw new IllegalStateException("Class "+_valueType.getName()+" does not have single-long constructor to use"); + } + return _longCtor.newInstance(l); + } +} diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java index 1723ca91..bd803f89 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java @@ -50,20 +50,18 @@ private POJODefinition _construct(Class beanType, int features) Map propsByName = new TreeMap<>(); _introspect(beanType, propsByName, features); - Constructor defaultCtor = null; - Constructor stringCtor = null; - Constructor longCtor = null; + final BeanConstructors constructors = new BeanConstructors(beanType); for (Constructor ctor : beanType.getDeclaredConstructors()) { Class[] argTypes = ctor.getParameterTypes(); if (argTypes.length == 0) { - defaultCtor = ctor; + constructors.addNoArgsConstructor(ctor); } else if (argTypes.length == 1) { Class argType = argTypes[0]; if (argType == String.class) { - stringCtor = ctor; + constructors.addStringConstructor(ctor); } else if (argType == Long.class || argType == Long.TYPE) { - longCtor = ctor; + constructors.addLongConstructor(ctor); } } } @@ -78,7 +76,7 @@ private POJODefinition _construct(Class beanType, int features) props[i++] = builder.build(); } } - return new POJODefinition(beanType, props, defaultCtor, stringCtor, longCtor); + return new POJODefinition(beanType, props, constructors); } private static void _introspect(Class currType, Map props, diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java index 826f1cc8..1f054d47 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java @@ -31,22 +31,23 @@ public class BeanReader // @since 2.11 protected final Set _ignorableNames; - protected final Constructor _defaultCtor; - protected final Constructor _stringCtor; - protected final Constructor _longCtor; + /** + * @since 2.17 + */ + protected final BeanConstructors _constructors; /** * Constructors used for deserialization use case + * + * @since 2.17 */ public BeanReader(Class type, Map props, - Constructor defaultCtor, Constructor stringCtor, Constructor longCtor, + BeanConstructors constructors, Set ignorableNames, Map aliasMapping) { super(type); _propsByName = props; - _defaultCtor = defaultCtor; - _stringCtor = stringCtor; - _longCtor = longCtor; + _constructors = constructors; if (ignorableNames == null) { ignorableNames = Collections.emptySet(); } @@ -57,6 +58,17 @@ public BeanReader(Class type, Map props, _aliasMapping = aliasMapping; } + @Deprecated // since 2.18 + public BeanReader(Class type, Map props, + Constructor defaultCtor, Constructor stringCtor, Constructor longCtor, + Set ignorableNames, Map aliasMapping) + { + this(type, props, new BeanConstructors(type).addNoArgsConstructor(defaultCtor) + .addStringConstructor(stringCtor) + .addLongConstructor(longCtor), + ignorableNames, aliasMapping); + } + @Deprecated // since 2.11 public BeanReader(Class type, Map props, Constructor defaultCtor, Constructor stringCtor, Constructor longCtor) { @@ -87,12 +99,12 @@ public Object readNext(JSONReader r, JsonParser p) throws IOException case VALUE_NULL: return null; case VALUE_STRING: - return create(p.getText()); + return _constructors.create(p.getText()); case VALUE_NUMBER_INT: - return create(p.getLongValue()); + return _constructors.create(p.getLongValue()); case START_OBJECT: { - Object bean = create(); + Object bean = _constructors.create(); final Object[] valueBuf = r._setterBuffer; String propName; @@ -138,12 +150,12 @@ public Object read(JSONReader r, JsonParser p) throws IOException case VALUE_NULL: return null; case VALUE_STRING: - return create(p.getText()); + return _constructors.create(p.getText()); case VALUE_NUMBER_INT: - return create(p.getLongValue()); + return _constructors.create(p.getLongValue()); case START_OBJECT: { - Object bean = create(); + Object bean = _constructors.create(); String propName; final Object[] valueBuf = r._setterBuffer; @@ -175,27 +187,6 @@ public Object read(JSONReader r, JsonParser p) throws IOException throw JSONObjectException.from(p, "Can not create a %s instance out of %s", _valueType.getName(), _tokenDesc(p)); } - - protected Object create() throws Exception { - if (_defaultCtor == null) { - throw new IllegalStateException("Class "+_valueType.getName()+" does not have default constructor to use"); - } - return _defaultCtor.newInstance((Object[]) null); - } - - protected Object create(String str) throws Exception { - if (_stringCtor == null) { - throw new IllegalStateException("Class "+_valueType.getName()+" does not have single-String constructor to use"); - } - return _stringCtor.newInstance(str); - } - - protected Object create(long l) throws Exception { - if (_longCtor == null) { - throw new IllegalStateException("Class "+_valueType.getName()+" does not have single-long constructor to use"); - } - return _longCtor.newInstance(l); - } protected void handleUnknown(JSONReader reader, JsonParser parser, String fieldName) throws IOException { if (JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY.isEnabled(reader._features)) { diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java index 0673c05a..a807983e 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java @@ -26,29 +26,40 @@ public class POJODefinition */ protected final Set _ignorableNames; - public final Constructor defaultCtor; - public final Constructor stringCtor; - public final Constructor longCtor; + /** + * @since 2.17 + */ + protected final BeanConstructors _constructors; + /** + * @since 2.17 + */ public POJODefinition(Class type, Prop[] props, - Constructor defaultCtor0, Constructor stringCtor0, Constructor longCtor0) + BeanConstructors constructors) { _type = type; _properties = props; - defaultCtor = defaultCtor0; - stringCtor = stringCtor0; - longCtor = longCtor0; + _constructors = constructors; _ignorableNames = null; } + @Deprecated // Since 2.17 + public POJODefinition(Class type, Prop[] props, + Constructor defaultCtor, Constructor stringCtor, Constructor longCtor) + { + this(type, props, + new BeanConstructors(type) + .addNoArgsConstructor(defaultCtor) + .addStringConstructor(stringCtor) + .addLongConstructor(longCtor)); + } + protected POJODefinition(POJODefinition base, Prop[] props, Set ignorableN) { _type = base._type; _properties = props; - defaultCtor = base.defaultCtor; - stringCtor = base.stringCtor; - longCtor = base.longCtor; + _constructors = base._constructors; _ignorableNames = ignorableN; } @@ -83,6 +94,13 @@ public Set getIgnorableNames() { return _ignorableNames; } + /** + * @since 2.17 + */ + public BeanConstructors constructors() { + return _constructors; + } + /* /********************************************************************** /* Helper class for containing property definitions diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java index c0bbb10c..2fb496e9 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java @@ -440,21 +440,10 @@ protected POJODefinition _resolveBeanDef(Class raw) { protected BeanReader _resolveBeanForDeser(Class raw, POJODefinition beanDef) { - Constructor defaultCtor = beanDef.defaultCtor; - Constructor stringCtor = beanDef.stringCtor; - Constructor longCtor = beanDef.longCtor; - + final BeanConstructors constructors = beanDef.constructors(); final boolean forceAccess = JSON.Feature.FORCE_REFLECTION_ACCESS.isEnabled(_features); if (forceAccess) { - if (defaultCtor != null) { - defaultCtor.setAccessible(true); - } - if (stringCtor != null) { - stringCtor.setAccessible(true); - } - if (longCtor != null) { - longCtor.setAccessible(true); - } + constructors.forceAccess(); } final boolean caseInsensitive = JSON.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES.isEnabled(_features); @@ -514,7 +503,7 @@ protected BeanReader _resolveBeanForDeser(Class raw, POJODefinition beanDef) } } } - return new BeanReader(raw, propMap, defaultCtor, stringCtor, longCtor, + return new BeanReader(raw, propMap, constructors, beanDef.getIgnorableNames(), aliasMapping); } diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 3fd427f5..b2dc5f9f 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -13,6 +13,7 @@ Modules: 2.17.0 (not yet released) +#25: Add support single-int Constructors #78: Deserializes "null" to "0.0" for `java.lang.Double` (wrapper) (reported by @bill-phast) #93: Skip serialization of `groovy.lang.MetaClass` values to avoid `StackOverflowError` From d0727e6f8e7da55e636ef1397f7693ebea220fda Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 23 Feb 2024 16:04:56 -0800 Subject: [PATCH 2/5] Complete implementation --- .../AnnotationBasedIntrospector.java | 2 ++ .../jackson/jr/ob/impl/BeanConstructors.java | 33 ++++++++++++++----- .../jr/ob/impl/BeanPropertyIntrospector.java | 2 ++ .../jackson/jr/ob/impl/BeanReader.java | 7 ++-- .../jackson/jr/ob/impl/POJODefinition.java | 5 --- .../jr/ob/impl/ValueReaderLocator.java | 8 ++--- .../{failing => ob}/ReadWithCtors25Test.java | 3 +- 7 files changed, 37 insertions(+), 23 deletions(-) rename jr-objects/src/test/java/com/fasterxml/jackson/jr/{failing => ob}/ReadWithCtors25Test.java (91%) diff --git a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java index 246e9de6..9ec3667e 100644 --- a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java +++ b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java @@ -99,6 +99,8 @@ protected POJODefinition introspectDefinition() Class argType = argTypes[0]; if (argType == String.class) { constructors.addStringConstructor(ctor); + } else if (argType == Integer.class || argType == Integer.TYPE) { + constructors.addIntConstructor(ctor); } else if (argType == Long.class || argType == Long.TYPE) { constructors.addLongConstructor(ctor); } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java index 0bd6def1..c8e12f9e 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java @@ -12,8 +12,10 @@ public class BeanConstructors protected final Class _valueType; protected Constructor _noArgsCtor; - protected Constructor _stringCtor; + + protected Constructor _intCtor; protected Constructor _longCtor; + protected Constructor _stringCtor; public BeanConstructors(Class valueType) { _valueType = valueType; @@ -24,8 +26,8 @@ public BeanConstructors addNoArgsConstructor(Constructor ctor) { return this; } - public BeanConstructors addStringConstructor(Constructor ctor) { - _stringCtor = ctor; + public BeanConstructors addIntConstructor(Constructor ctor) { + _intCtor = ctor; return this; } @@ -34,16 +36,24 @@ public BeanConstructors addLongConstructor(Constructor ctor) { return this; } + public BeanConstructors addStringConstructor(Constructor ctor) { + _stringCtor = ctor; + return this; + } + public void forceAccess() { if (_noArgsCtor != null) { _noArgsCtor.setAccessible(true); } - if (_stringCtor != null) { - _stringCtor.setAccessible(true); + if (_intCtor != null) { + _intCtor.setAccessible(true); } if (_longCtor != null) { _longCtor.setAccessible(true); } + if (_stringCtor != null) { + _stringCtor.setAccessible(true); + } } protected Object create() throws Exception { @@ -61,9 +71,16 @@ protected Object create(String str) throws Exception { } protected Object create(long l) throws Exception { - if (_longCtor == null) { - throw new IllegalStateException("Class "+_valueType.getName()+" does not have single-long constructor to use"); + // 23-Feb-2024, tatu: As per [jackson-jr#25] can have `int`-constructors too. + // For now no need to try to optimize separately + if (_longCtor != null) { + return _longCtor.newInstance(l); + } + if (_intCtor != null) { + // TODO: should this do bounds checks? + return _intCtor.newInstance((int) l); } - return _longCtor.newInstance(l); + throw new IllegalStateException("Class "+_valueType.getName() + +" does not have single-long or single-int constructor to use"); } } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java index bd803f89..27d78f6f 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java @@ -60,6 +60,8 @@ private POJODefinition _construct(Class beanType, int features) Class argType = argTypes[0]; if (argType == String.class) { constructors.addStringConstructor(ctor); + } else if (argType == Integer.class || argType == Integer.TYPE) { + constructors.addIntConstructor(ctor); } else if (argType == Long.class || argType == Long.TYPE) { constructors.addLongConstructor(ctor); } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java index 1f054d47..5903ef46 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java @@ -107,7 +107,7 @@ public Object readNext(JSONReader r, JsonParser p) throws IOException Object bean = _constructors.create(); final Object[] valueBuf = r._setterBuffer; String propName; - + for (; (propName = p.nextFieldName()) != null; ) { BeanPropertyReader prop = findProperty(propName); if (prop == null) { @@ -158,7 +158,7 @@ public Object read(JSONReader r, JsonParser p) throws IOException Object bean = _constructors.create(); String propName; final Object[] valueBuf = r._setterBuffer; - + for (; (propName = p.nextFieldName()) != null; ) { BeanPropertyReader prop = findProperty(propName); if (prop == null) { @@ -171,8 +171,7 @@ public Object read(JSONReader r, JsonParser p) throws IOException // also verify we are not confused... if (!p.hasToken(JsonToken.END_OBJECT)) { throw _reportProblem(p); - } - + } return bean; } default: diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java index a807983e..e14ee67b 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/POJODefinition.java @@ -82,11 +82,6 @@ public List getProperties() { return Arrays.asList(_properties); } - @Deprecated // in 2.11, will be removed soon - public Prop[] properties() { - return _properties; - } - public Set getIgnorableNames() { if (_ignorableNames == null) { return Collections.emptySet(); diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java index 2fb496e9..35638b5c 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java @@ -456,9 +456,9 @@ protected BeanReader _resolveBeanForDeser(Class raw, POJODefinition beanDef) propMap = Collections.emptyMap(); } else { propMap = caseInsensitive - ? new TreeMap(String.CASE_INSENSITIVE_ORDER) + ? new TreeMap<>(String.CASE_INSENSITIVE_ORDER) // 13-May-2021, tatu: Let's retain ordering here: - : new LinkedHashMap(); + : new LinkedHashMap<>(); final boolean useFields = JSON.Feature.USE_FIELDS.isEnabled(_features); for (int i = 0; i < len; ++i) { POJODefinition.Prop rawProp = rawProps.get(i); @@ -494,8 +494,8 @@ protected BeanReader _resolveBeanForDeser(Class raw, POJODefinition beanDef) if (rawProp.hasAliases()) { if (aliasMapping == null) { aliasMapping = caseInsensitive - ? new TreeMap(String.CASE_INSENSITIVE_ORDER) - : new HashMap(); + ? new TreeMap<>(String.CASE_INSENSITIVE_ORDER) + : new HashMap<>(); } for (String alias : rawProp.aliases()) { aliasMapping.put(alias, rawProp.name); diff --git a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadWithCtors25Test.java b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtors25Test.java similarity index 91% rename from jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadWithCtors25Test.java rename to jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtors25Test.java index 4b9e5c5f..78703ff5 100644 --- a/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/ReadWithCtors25Test.java +++ b/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/ReadWithCtors25Test.java @@ -1,7 +1,6 @@ -package com.fasterxml.jackson.jr.failing; +package com.fasterxml.jackson.jr.ob; import com.fasterxml.jackson.jr.ob.JSON; -import com.fasterxml.jackson.jr.ob.TestBase; // for [jackson-jr#25], allowing single-int constructors public class ReadWithCtors25Test extends TestBase From 170615a09eb4a4107309a113caadae023009155a Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 23 Feb 2024 16:10:54 -0800 Subject: [PATCH 3/5] Minor optimization --- .../AnnotationBasedIntrospector.java | 2 +- .../jackson/jr/ob/impl/BeanConstructors.java | 7 ++-- .../jr/ob/impl/BeanPropertyIntrospector.java | 41 +++++++++++-------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java index 9ec3667e..4a24c0af 100644 --- a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java +++ b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java @@ -44,7 +44,7 @@ public class AnnotationBasedIntrospector protected int _features; protected AnnotationBasedIntrospector(Class type, boolean serialization, - JsonAutoDetect.Value visibility, int features) { + JsonAutoDetect.Value visibility, int features) { _type = type; _forSerialization = serialization; _ignorableNames = serialization ? null : new HashSet(); diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java index c8e12f9e..157a763d 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanConstructors.java @@ -3,9 +3,10 @@ import java.lang.reflect.Constructor; /** - * Container class added in 2.17 to encapsulate collection and use - * of various Constructors for User-defined (non-JDK) types (aka - * "Beans"). + * Container class added to encapsulate details of collection and use of + * Constructors for User-defined (non-JDK) types (aka "Beans"). + * + * @since 2.17 */ public class BeanConstructors { diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java index 27d78f6f..59548f8d 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanPropertyIntrospector.java @@ -32,11 +32,11 @@ public BeanPropertyIntrospector() { } public static BeanPropertyIntrospector instance() { return INSTANCE; } public POJODefinition pojoDefinitionForDeserialization(JSONReader r, Class pojoType) { - return _construct(pojoType, r.features()); + return _introspectDefinition(pojoType, false, r.features()); } public POJODefinition pojoDefinitionForSerialization(JSONWriter w, Class pojoType) { - return _construct(pojoType, w.features()); + return _introspectDefinition(pojoType, true, w.features()); } /* @@ -45,28 +45,35 @@ public POJODefinition pojoDefinitionForSerialization(JSONWriter w, Class pojo /********************************************************************** */ - private POJODefinition _construct(Class beanType, int features) + private POJODefinition _introspectDefinition(Class beanType, + boolean forSerialization, int features) { Map propsByName = new TreeMap<>(); _introspect(beanType, propsByName, features); - final BeanConstructors constructors = new BeanConstructors(beanType); - - for (Constructor ctor : beanType.getDeclaredConstructors()) { - Class[] argTypes = ctor.getParameterTypes(); - if (argTypes.length == 0) { - constructors.addNoArgsConstructor(ctor); - } else if (argTypes.length == 1) { - Class argType = argTypes[0]; - if (argType == String.class) { - constructors.addStringConstructor(ctor); - } else if (argType == Integer.class || argType == Integer.TYPE) { - constructors.addIntConstructor(ctor); - } else if (argType == Long.class || argType == Long.TYPE) { - constructors.addLongConstructor(ctor); + final BeanConstructors constructors; + + if (forSerialization) { + constructors = null; + } else { + constructors = new BeanConstructors(beanType); + for (Constructor ctor : beanType.getDeclaredConstructors()) { + Class[] argTypes = ctor.getParameterTypes(); + if (argTypes.length == 0) { + constructors.addNoArgsConstructor(ctor); + } else if (argTypes.length == 1) { + Class argType = argTypes[0]; + if (argType == String.class) { + constructors.addStringConstructor(ctor); + } else if (argType == Integer.class || argType == Integer.TYPE) { + constructors.addIntConstructor(ctor); + } else if (argType == Long.class || argType == Long.TYPE) { + constructors.addLongConstructor(ctor); + } } } } + final int len = propsByName.size(); Prop[] props; if (len == 0) { From a470872e74c626e3f5a87740dfde8cc0dffa9ce5 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 23 Feb 2024 16:20:47 -0800 Subject: [PATCH 4/5] ... --- .../jr/annotationsupport/AnnotationBasedIntrospector.java | 2 +- .../main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java index 4a24c0af..314fa9eb 100644 --- a/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java +++ b/jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java @@ -83,7 +83,7 @@ protected POJODefinition introspectDefinition() _findFields(); _findMethods(); - BeanConstructors constructors = null; + final BeanConstructors constructors; // A few things only matter during deserialization: constructors, // secondary ignoral information: diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java index 5903ef46..c07974b3 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/BeanReader.java @@ -58,7 +58,7 @@ public BeanReader(Class type, Map props, _aliasMapping = aliasMapping; } - @Deprecated // since 2.18 + @Deprecated // since 2.17 public BeanReader(Class type, Map props, Constructor defaultCtor, Constructor stringCtor, Constructor longCtor, Set ignorableNames, Map aliasMapping) From e19c79c183a40b874dfa886f27995b22cf5ed534 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 23 Feb 2024 16:21:45 -0800 Subject: [PATCH 5/5] ... --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9c8bce9..1ebb7f0f 100644 --- a/README.md +++ b/README.md @@ -241,7 +241,7 @@ You can use Maven dependency like: com.fasterxml.jackson.jr jackson-jr-objects - 2.13.0 + 2.16.1 ```