diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/DefaultAccessorNamingStrategy.java b/src/main/java/com/fasterxml/jackson/databind/introspect/DefaultAccessorNamingStrategy.java index 30c57e2ea9..057f0db08c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/DefaultAccessorNamingStrategy.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/DefaultAccessorNamingStrategy.java @@ -19,9 +19,25 @@ public class DefaultAccessorNamingStrategy extends AccessorNamingStrategy { + /** + * Definition of a handler API to use for checking whether given base name + * (remainder of accessor method name after removing prefix) is acceptable + * based on various rules. + * + * @since 2.12 + */ + public interface BaseNameValidator { + public boolean accept(char firstChar, String basename, int offset); + } + protected final MapperConfig _config; protected final AnnotatedClass _forClass; + /** + * Optional validator for checking that base name + */ + protected final BaseNameValidator _baseNameValidator; + protected final boolean _stdBeanNaming; protected final String _getterPrefix; @@ -34,7 +50,8 @@ public class DefaultAccessorNamingStrategy protected final String _mutatorPrefix; protected DefaultAccessorNamingStrategy(MapperConfig config, AnnotatedClass forClass, - String mutatorPrefix, String getterPrefix, String isGetterPrefix) + String mutatorPrefix, String getterPrefix, String isGetterPrefix, + BaseNameValidator baseNameValidator) { _config = config; _forClass = forClass; @@ -43,6 +60,7 @@ protected DefaultAccessorNamingStrategy(MapperConfig config, AnnotatedClass f _mutatorPrefix = mutatorPrefix; _getterPrefix = getterPrefix; _isGetterPrefix = isGetterPrefix; + _baseNameValidator = baseNameValidator; } @Override @@ -116,14 +134,22 @@ public String modifyFieldName(AnnotatedField field, String name) { * @param basename Name of accessor/mutator method, not including prefix * ("get"/"is"/"set") */ - protected static String legacyManglePropertyName(final String basename, final int offset) + protected 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); + // 12-Oct-2020, tatu: Additional configurability; allow checking that + // base name is acceptable (currently just by checking first character) + if (_baseNameValidator != null) { + if (!_baseNameValidator.accept(c, basename, offset)) { + return null; + } + } + + // next check: is the first character upper case? If not, return as is char d = Character.toLowerCase(c); if (c == d) { @@ -145,7 +171,7 @@ protected static String legacyManglePropertyName(final String basename, final in return sb.toString(); } - protected static String stdManglePropertyName(final String basename, final int offset) + protected String stdManglePropertyName(final String basename, final int offset) { final int end = basename.length(); if (end == offset) { // empty name, nope @@ -153,6 +179,14 @@ protected static String stdManglePropertyName(final String basename, final int o } // first: if it doesn't start with capital, return as-is char c0 = basename.charAt(offset); + // 12-Oct-2020, tatu: Additional configurability; allow checking that + // base name is acceptable (currently just by checking first character) + if (_baseNameValidator != null) { + if (!_baseNameValidator.accept(c0, basename, offset)) { + return null; + } + } + char c1 = Character.toLowerCase(c0); if (c0 == c1) { return basename.substring(offset); @@ -230,8 +264,9 @@ protected boolean _isGroovyMetaClassGetter(AnnotatedMethod am) { *
  • Is-getter (for Boolean values): "is" *
  • *