@@ -27,6 +27,17 @@ public class DefaultAccessorNamingStrategy
27
27
* based on various rules.
28
28
*/
29
29
public interface BaseNameValidator {
30
+ /**
31
+ * Method called to check whether given base name is acceptable: called
32
+ * for accessor method name after removing prefix.
33
+ * NOTE: called even if "prefix" is empy (i.e. nothing really removed)
34
+ *
35
+ * @param firstChar First character of the base name
36
+ * @param basename Full base name (after removing prefix)
37
+ * @param offset Length of prefix removed
38
+ *
39
+ * @return {@ocode true} if base name is acceptable; {@code false} otherwise
40
+ */
30
41
public boolean accept (char firstChar , String basename , int offset );
31
42
}
32
43
@@ -239,16 +250,19 @@ protected boolean _isGroovyMetaClassGetter(AnnotatedMethod am) {
239
250
* <li>Is-getter (for Boolean values): "is"
240
251
* </li>
241
252
*</ul>
242
- * and no additional restrictions on base names accepted (configurable for
243
- * limits using {@link BaseNameValidator}), allowing names like
244
- * "get_value()" and "getvalue()".
253
+ * with additional restrictions on base names accepted (configurable for
254
+ * limits using {@link BaseNameValidator}), preventing names like
255
+ * "get_value()" and "getvalue()" (unlike Jackson 2.x that allowed these) .
245
256
*/
246
257
public static class Provider
247
258
extends AccessorNamingStrategy .Provider
248
259
implements java .io .Serializable
249
260
{
250
261
private static final long serialVersionUID = 1L ;
251
262
263
+ private static final BaseNameValidator DEFAULT_BASE_NAME_VALIDATOR
264
+ = FirstCharBasedValidator .forFirstNameRule (false , false );
265
+
252
266
protected final String _setterPrefix ;
253
267
protected final String _withPrefix ;
254
268
@@ -259,7 +273,7 @@ public static class Provider
259
273
260
274
public Provider () {
261
275
this ("set" , JsonPOJOBuilder .DEFAULT_WITH_PREFIX ,
262
- "get" , "is" , null );
276
+ "get" , "is" , DEFAULT_BASE_NAME_VALIDATOR );
263
277
}
264
278
265
279
protected Provider (Provider p ,
@@ -380,7 +394,8 @@ public Provider withIsGetterPrefix(String prefix) {
380
394
public Provider withFirstCharAcceptance (boolean allowLowerCaseFirstChar ,
381
395
boolean allowNonLetterFirstChar ) {
382
396
return withBaseNameValidator (
383
- FirstCharBasedValidator .forFirstNameRule (allowLowerCaseFirstChar , allowNonLetterFirstChar ));
397
+ FirstCharBasedValidator .forFirstNameRule (allowLowerCaseFirstChar ,
398
+ allowNonLetterFirstChar ));
384
399
}
385
400
386
401
/**
@@ -409,7 +424,8 @@ public AccessorNamingStrategy forPOJO(MapperConfig<?> config, AnnotatedClass tar
409
424
public AccessorNamingStrategy forBuilder (MapperConfig <?> config ,
410
425
AnnotatedClass builderClass , BeanDescription valueTypeDesc )
411
426
{
412
- AnnotationIntrospector ai = config .isAnnotationProcessingEnabled () ? config .getAnnotationIntrospector () : null ;
427
+ AnnotationIntrospector ai = config .isAnnotationProcessingEnabled ()
428
+ ? config .getAnnotationIntrospector () : null ;
413
429
JsonPOJOBuilder .Value builderConfig = (ai == null ) ? null : ai .findPOJOBuilderConfig (config , builderClass );
414
430
String mutatorPrefix = (builderConfig == null ) ? _withPrefix : builderConfig .withPrefix ;
415
431
return new DefaultAccessorNamingStrategy (config , builderClass ,
@@ -426,14 +442,17 @@ public AccessorNamingStrategy forRecord(MapperConfig<?> config, AnnotatedClass r
426
442
427
443
/**
428
444
* Simple implementation of {@link BaseNameValidator} that checks the
429
- * first character and nothing else.
445
+ * first character and nothing else if (and only if!) prefix is empty
446
+ * (so {@code offset} passed is NOT zero).
430
447
*<p>
431
448
* Instances are to be constructed using method
432
449
* {@link FirstCharBasedValidator#forFirstNameRule}.
433
450
*/
434
451
public static class FirstCharBasedValidator
435
- implements BaseNameValidator
452
+ implements BaseNameValidator , java . io . Serializable
436
453
{
454
+ private static final long serialVersionUID = 3L ;
455
+
437
456
private final boolean _allowLowerCaseFirstChar ;
438
457
private final boolean _allowNonLetterFirstChar ;
439
458
@@ -468,6 +487,14 @@ public static BaseNameValidator forFirstNameRule(boolean allowLowerCaseFirstChar
468
487
469
488
@ Override
470
489
public boolean accept (char firstChar , String basename , int offset ) {
490
+ // 27-Mar-2025, tatu: [databind#2882] Need to make sure we don't
491
+ // try to validate cases where no prefix is removed (mostly case
492
+ // for builders, but also for Record-style plain "getters" and
493
+ // "setters".
494
+ if (offset == 0 ) {
495
+ return true ;
496
+ }
497
+
471
498
// Ok, so... If UTF-16 letter, then check whether lc allowed
472
499
// (title-case and upper-case both assumed to be acceptable by default)
473
500
if (Character .isLetter (firstChar )) {
0 commit comments