@@ -259,9 +259,11 @@ public AnnotatedMember getJsonKeyAccessor() {
259
259
// If @JsonKey defined, must have a single one
260
260
if (_jsonKeyAccessors != null ) {
261
261
if (_jsonKeyAccessors .size () > 1 ) {
262
- reportProblem ("Multiple 'as-key' properties defined (%s vs %s)" ,
263
- _jsonKeyAccessors .get (0 ),
264
- _jsonKeyAccessors .get (1 ));
262
+ if (!_resolveFieldVsGetter (_jsonKeyAccessors )) {
263
+ reportProblem ("Multiple 'as-key' properties defined (%s vs %s)" ,
264
+ _jsonKeyAccessors .get (0 ),
265
+ _jsonKeyAccessors .get (1 ));
266
+ }
265
267
}
266
268
// otherwise we won't greatly care
267
269
return _jsonKeyAccessors .get (0 );
@@ -278,11 +280,14 @@ public AnnotatedMember getJsonValueAccessor()
278
280
collectAll ();
279
281
}
280
282
// If @JsonValue defined, must have a single one
283
+ // 15-Jan-2023, tatu: Except let's try resolving "getter-over-field" case at least
281
284
if (_jsonValueAccessors != null ) {
282
285
if (_jsonValueAccessors .size () > 1 ) {
283
- reportProblem ("Multiple 'as-value' properties defined (%s vs %s)" ,
284
- _jsonValueAccessors .get (0 ),
285
- _jsonValueAccessors .get (1 ));
286
+ if (!_resolveFieldVsGetter (_jsonValueAccessors )) {
287
+ reportProblem ("Multiple 'as-value' properties defined (%s vs %s)" ,
288
+ _jsonValueAccessors .get (0 ),
289
+ _jsonValueAccessors .get (1 ));
290
+ }
286
291
}
287
292
// otherwise we won't greatly care
288
293
return _jsonValueAccessors .get (0 );
@@ -1189,7 +1194,7 @@ protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
1189
1194
1190
1195
/*
1191
1196
/**********************************************************
1192
- /* Overridable internal methods, sorting, other stuff
1197
+ /* Internal methods, sorting
1193
1198
/**********************************************************
1194
1199
*/
1195
1200
@@ -1310,6 +1315,48 @@ private boolean _anyIndexed(Collection<POJOPropertyBuilder> props) {
1310
1315
return false ;
1311
1316
}
1312
1317
1318
+ /*
1319
+ /**********************************************************
1320
+ /* Internal methods, conflict resolution
1321
+ /**********************************************************
1322
+ */
1323
+
1324
+ /**
1325
+ * Method that will be given a {@link List} with 2 or more accessors
1326
+ * that may be in conflict: it will need to remove lower-priority accessors
1327
+ * to leave just a single highest-priority accessor to use.
1328
+ * If this succeeds method returns {@code true}, otherwise {@code false}.
1329
+ *<p>
1330
+ * NOTE: method will directly modify given {@code List} directly, regardless
1331
+ * of whether it ultimately succeeds or not.
1332
+ *
1333
+ * @return True if seeming conflict was resolved and there only remains
1334
+ * single accessor
1335
+ */
1336
+ protected boolean _resolveFieldVsGetter (List <AnnotatedMember > accessors ) {
1337
+ do {
1338
+ AnnotatedMember acc1 = accessors .get (0 );
1339
+ AnnotatedMember acc2 = accessors .get (1 );
1340
+
1341
+ if (acc1 instanceof AnnotatedField ) {
1342
+ if (acc2 instanceof AnnotatedMethod ) {
1343
+ // Method has precedence, remove first entry
1344
+ accessors .remove (0 );
1345
+ continue ;
1346
+ }
1347
+ } else if (acc1 instanceof AnnotatedMethod ) {
1348
+ // Method has precedence, remove second entry
1349
+ if (acc2 instanceof AnnotatedField ) {
1350
+ accessors .remove (1 );
1351
+ continue ;
1352
+ }
1353
+ }
1354
+ // Not a field/method pair; fail
1355
+ return false ;
1356
+ } while (accessors .size () > 1 );
1357
+ return true ;
1358
+ }
1359
+
1313
1360
/*
1314
1361
/**********************************************************
1315
1362
/* Internal methods; helpers
0 commit comments