From 21228631e85194410e6dfeabb263dfc028e71eb6 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sun, 24 Sep 2017 15:38:22 -0700 Subject: [PATCH] Fix #1772 --- release-notes/VERSION | 2 + .../jackson/databind/MapperFeature.java | 16 ---- .../introspect/POJOPropertiesCollector.java | 16 ++-- .../jackson/databind/util/BeanUtil.java | 89 ++++--------------- .../databind/introspect/BeanNamingTest.java | 16 ++-- .../jackson/databind/util/BeanUtilTest.java | 30 ++----- 6 files changed, 33 insertions(+), 136 deletions(-) diff --git a/release-notes/VERSION b/release-notes/VERSION index 70c94f41c0..c4b034f507 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -8,3 +8,5 @@ Versions: 3.x (for earlier see VERSION-2.x) 3.0.0 (not yet released) #1762: `StdDateFormat`: serialize time offset using colon +#1772: Remove `MapperFeature. USE_STD_BEAN_NAMING` + diff --git a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java index 967fb89640..58a5e6dd15 100644 --- a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java +++ b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java @@ -382,22 +382,6 @@ public enum MapperFeature implements ConfigFeature */ USE_WRAPPER_NAME_AS_PROPERTY_NAME(false), - /** - * Feature that may be enabled to enforce strict compatibility with - * Bean name introspection, instead of slightly different mechanism - * Jackson defaults to. - * Specific difference is that Jackson always lower cases leading upper-case - * letters, so "getURL()" becomes "url" property; whereas standard Bean - * naming only lower-cases the first letter if it is NOT followed by - * another upper-case letter (so "getURL()" would result in "URL" property). - *

- * Feature is disabled by default for backwards compatibility purposes: earlier - * Jackson versions used Jackson's own mechanism. - * - * @since 2.5 - */ - USE_STD_BEAN_NAMING(false), - /** * Feature that when enabled will allow explicitly named properties (i.e., fields or methods * annotated with {@link com.fasterxml.jackson.annotation.JsonProperty}("explicitName")) to diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java index 09b4f4cdcf..f296f6fef8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java @@ -37,11 +37,6 @@ public class POJOPropertiesCollector */ protected final boolean _forSerialization; - /** - * @since 2.5 - */ - protected final boolean _stdBeanNaming; - /** * Type of POJO for which properties are being collected. */ @@ -127,7 +122,6 @@ protected POJOPropertiesCollector(MapperConfig config, boolean forSerializati JavaType type, AnnotatedClass classDef, String mutatorPrefix) { _config = config; - _stdBeanNaming = config.isEnabled(MapperFeature.USE_STD_BEAN_NAMING); _forSerialization = forSerialization; _type = type; _classDef = classDef; @@ -566,10 +560,10 @@ protected void _addGetterMethod(Map props, if (!nameExplicit) { // no explicit name; must consider implicit implName = ai.findImplicitPropertyName(m); if (implName == null) { - implName = BeanUtil.okNameForRegularGetter(m, m.getName(), _stdBeanNaming); + implName = BeanUtil.okNameForRegularGetter(m, m.getName()); } if (implName == null) { // if not, must skip - implName = BeanUtil.okNameForIsGetter(m, m.getName(), _stdBeanNaming); + implName = BeanUtil.okNameForIsGetter(m, m.getName()); if (implName == null) { return; } @@ -581,7 +575,7 @@ protected void _addGetterMethod(Map props, // we still need implicit name to link with other pieces implName = ai.findImplicitPropertyName(m); if (implName == null) { - implName = BeanUtil.okNameForGetter(m, _stdBeanNaming); + implName = BeanUtil.okNameForGetter(m); } // if not regular getter name, use method name as is if (implName == null) { @@ -608,7 +602,7 @@ protected void _addSetterMethod(Map props, if (!nameExplicit) { // no explicit name; must follow naming convention implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { - implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); + implName = BeanUtil.okNameForMutator(m, _mutatorPrefix); } if (implName == null) { // if not, must skip return; @@ -618,7 +612,7 @@ protected void _addSetterMethod(Map props, // we still need implicit name to link with other pieces implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { - implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); + implName = BeanUtil.okNameForMutator(m, _mutatorPrefix); } // if not regular getter name, use method name as is if (implName == null) { diff --git a/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java index 7ebfe609c1..5c8f66b809 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java @@ -6,7 +6,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** * Helper class that contains functionality needed by both serialization @@ -20,17 +20,16 @@ public class BeanUtil /********************************************************** */ - public static String okNameForGetter(AnnotatedMethod am, boolean stdNaming) { + public static String okNameForGetter(AnnotatedMember am) { String name = am.getName(); - String str = okNameForIsGetter(am, name, stdNaming); + String str = okNameForIsGetter(am, name); if (str == null) { - str = okNameForRegularGetter(am, name, stdNaming); + str = okNameForRegularGetter(am, name); } return str; } - public static String okNameForRegularGetter(AnnotatedMethod am, String name, - boolean stdNaming) + public static String okNameForRegularGetter(AnnotatedMember am, String name) { if (name.startsWith("get")) { /* 16-Feb-2009, tatu: To handle [JACKSON-53], need to block @@ -50,38 +49,27 @@ public static String okNameForRegularGetter(AnnotatedMethod am, String name, return null; } } - return stdNaming - ? stdManglePropertyName(name, 3) - : legacyManglePropertyName(name, 3); + return stdManglePropertyName(name, 3); } return null; } - /** - * @since 2.5 - */ - public static String okNameForIsGetter(AnnotatedMethod am, String name, - boolean stdNaming) + public static String okNameForIsGetter(AnnotatedMember am, String name) { if (name.startsWith("is")) { // plus, must return a boolean Class rt = am.getRawType(); if (rt == Boolean.class || rt == Boolean.TYPE) { - return stdNaming - ? stdManglePropertyName(name, 2) - : legacyManglePropertyName(name, 2); + return stdManglePropertyName(name, 2); } } return null; } - public static String okNameForMutator(AnnotatedMethod am, String prefix, - boolean stdNaming) + public static String okNameForMutator(AnnotatedMember am, String prefix) { String name = am.getName(); if (name.startsWith(prefix)) { - return stdNaming - ? stdManglePropertyName(name, prefix.length()) - : legacyManglePropertyName(name, prefix.length()); + return stdManglePropertyName(name, prefix.length()); } return null; } @@ -148,7 +136,7 @@ public static Object getDefaultValue(JavaType type) * indeed injectect by Cglib. We do this by verifying that the * result type is "net.sf.cglib.proxy.Callback[]" */ - protected static boolean isCglibGetCallbacks(AnnotatedMethod am) + protected static boolean isCglibGetCallbacks(AnnotatedMember am) { Class rt = am.getRawType(); // Ok, first: must return an array type @@ -173,21 +161,10 @@ protected static boolean isCglibGetCallbacks(AnnotatedMethod am) return false; } - /** - * Similar to {@link #isCglibGetCallbacks}, need to suppress - * a cyclic reference. - */ - protected static boolean isGroovyMetaClassSetter(AnnotatedMethod am) - { - Class argType = am.getRawParameterType(0); - String pkgName = ClassUtil.getPackageName(argType); - return (pkgName != null) && pkgName.startsWith("groovy.lang"); - } - /** * Another helper method to deal with Groovy's problematic metadata accessors */ - protected static boolean isGroovyMetaClassGetter(AnnotatedMethod am) + protected static boolean isGroovyMetaClassGetter(AnnotatedMember am) { String pkgName = ClassUtil.getPackageName(am.getRawType()); return (pkgName != null) && pkgName.startsWith("groovy.lang"); @@ -199,45 +176,9 @@ protected static boolean isGroovyMetaClassGetter(AnnotatedMethod am) /********************************************************** */ - /** - * Method called to figure out name of the property, given - * corresponding suggested name based on a method or field name. - * - * @param basename Name of accessor/mutator method, not including prefix - * ("get"/"is"/"set") - */ - protected static String legacyManglePropertyName(final String basename, final int offset) - { - final int end = basename.length(); - if (end == offset) { // empty name, nope - return null; - } - // next check: is the first character upper case? If not, return as is - char c = basename.charAt(offset); - char d = Character.toLowerCase(c); - - if (c == d) { - return basename.substring(offset); - } - // otherwise, lower case initial chars. Common case first, just one char - StringBuilder sb = new StringBuilder(end - offset); - sb.append(d); - int i = offset+1; - for (; i < end; ++i) { - c = basename.charAt(i); - d = Character.toLowerCase(c); - if (c == d) { - sb.append(basename, i, end); - break; - } - sb.append(d); - } - return sb.toString(); - } - - /** - * @since 2.5 - */ + // 24-Sep-2017, tatu: note that "std" here refers to earlier (1.x, 2.x) distinction + // between "legacy" (slightly non-conforming) and "std" (fully conforming): with 3.x + // only latter exists. protected static String stdManglePropertyName(final String basename, final int offset) { final int end = basename.length(); diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java index d01de89050..e840d41f0c 100644 --- a/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java @@ -16,18 +16,12 @@ public int getA() { return 3; } } - - public void testSimple() throws Exception - { - ObjectMapper mapper = new ObjectMapper(); - assertFalse(mapper.isEnabled(MapperFeature.USE_STD_BEAN_NAMING)); - assertEquals(aposToQuotes("{'url':'http://foo'}"), - mapper.writeValueAsString(new URLBean())); - assertEquals(aposToQuotes("{'a':3}"), - mapper.writeValueAsString(new ABean())); - mapper = new ObjectMapper(); - mapper.enable(MapperFeature.USE_STD_BEAN_NAMING); + // 24-Sep-2017, tatu: Used to test for `MapperFeature.USE_STD_BEAN_NAMING`, but with 3.x + // that is always enabled. + public void testMultipleLeadingCapitalLetters() throws Exception + { + ObjectMapper mapper = objectMapper(); assertEquals(aposToQuotes("{'URL':'http://foo'}"), mapper.writeValueAsString(new URLBean())); assertEquals(aposToQuotes("{'a':3}"), diff --git a/src/test/java/com/fasterxml/jackson/databind/util/BeanUtilTest.java b/src/test/java/com/fasterxml/jackson/databind/util/BeanUtilTest.java index 83ba5fbfac..dcf25a184d 100644 --- a/src/test/java/com/fasterxml/jackson/databind/util/BeanUtilTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/util/BeanUtilTest.java @@ -37,10 +37,8 @@ public void set() { } public void testNameMangle() { - assertEquals("foo", BeanUtil.legacyManglePropertyName("getFoo", 3)); assertEquals("foo", BeanUtil.stdManglePropertyName("getFoo", 3)); - assertEquals("url", BeanUtil.legacyManglePropertyName("getURL", 3)); assertEquals("URL", BeanUtil.stdManglePropertyName("getURL", 3)); } @@ -98,45 +96,29 @@ public void testOkNameForSetter() throws Exception */ private void _testIsGetter(String name, String expName) throws Exception { - _testIsGetter(name, expName, true); - _testIsGetter(name, expName, false); - } - - private void _testIsGetter(String name, String expName, boolean useStd) throws Exception - { AnnotatedMethod m = _method(IsGetters.class, name); if (expName == null) { - assertNull(BeanUtil.okNameForIsGetter(m, name, useStd)); + assertNull(BeanUtil.okNameForIsGetter(m, name)); } else { - assertEquals(expName, BeanUtil.okNameForIsGetter(m, name, useStd)); + assertEquals(expName, BeanUtil.okNameForIsGetter(m, name)); } } private void _testOkNameForGetter(String name, String expName) throws Exception { - _testOkNameForGetter(name, expName, true); - _testOkNameForGetter(name, expName, false); - } - - private void _testOkNameForGetter(String name, String expName, boolean useStd) throws Exception { AnnotatedMethod m = _method(Getters.class, name); if (expName == null) { - assertNull(BeanUtil.okNameForGetter(m, useStd)); + assertNull(BeanUtil.okNameForGetter(m)); } else { - assertEquals(expName, BeanUtil.okNameForGetter(m, useStd)); + assertEquals(expName, BeanUtil.okNameForGetter(m)); } } private void _testOkNameForMutator(String name, String expName) throws Exception { - _testOkNameForMutator(name, expName, true); - _testOkNameForMutator(name, expName, false); - } - - private void _testOkNameForMutator(String name, String expName, boolean useStd) throws Exception { AnnotatedMethod m = _method(Setters.class, name); if (expName == null) { - assertNull(BeanUtil.okNameForMutator(m, "set", useStd)); + assertNull(BeanUtil.okNameForMutator(m, "set")); } else { - assertEquals(expName, BeanUtil.okNameForMutator(m, "set", useStd)); + assertEquals(expName, BeanUtil.okNameForMutator(m, "set")); } }