@@ -251,9 +251,11 @@ public AnnotatedMember getJsonKeyAccessor() {
251
251
// If @JsonKey defined, must have a single one
252
252
if (_jsonKeyAccessors != null ) {
253
253
if (_jsonKeyAccessors .size () > 1 ) {
254
- reportProblem ("Multiple 'as-key' properties defined (%s vs %s)" ,
255
- _jsonKeyAccessors .get (0 ),
256
- _jsonKeyAccessors .get (1 ));
254
+ if (!_resolveFieldVsGetter (_jsonKeyAccessors )) {
255
+ reportProblem ("Multiple 'as-key' properties defined (%s vs %s)" ,
256
+ _jsonKeyAccessors .get (0 ),
257
+ _jsonKeyAccessors .get (1 ));
258
+ }
257
259
}
258
260
// otherwise we won't greatly care
259
261
return _jsonKeyAccessors .get (0 );
@@ -270,11 +272,14 @@ public AnnotatedMember getJsonValueAccessor()
270
272
collectAll ();
271
273
}
272
274
// If @JsonValue defined, must have a single one
275
+ // 15-Jan-2023, tatu: Except let's try resolving "getter-over-field" case at least
273
276
if (_jsonValueAccessors != null ) {
274
277
if (_jsonValueAccessors .size () > 1 ) {
275
- reportProblem ("Multiple 'as-value' properties defined (%s vs %s)" ,
276
- _jsonValueAccessors .get (0 ),
277
- _jsonValueAccessors .get (1 ));
278
+ if (!_resolveFieldVsGetter (_jsonValueAccessors )) {
279
+ reportProblem ("Multiple 'as-value' properties defined (%s vs %s)" ,
280
+ _jsonValueAccessors .get (0 ),
281
+ _jsonValueAccessors .get (1 ));
282
+ }
278
283
}
279
284
// otherwise we won't greatly care
280
285
return _jsonValueAccessors .get (0 );
@@ -1123,7 +1128,7 @@ protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
1123
1128
1124
1129
/*
1125
1130
/**********************************************************
1126
- /* Overridable internal methods, sorting, other stuff
1131
+ /* Internal methods, sorting
1127
1132
/**********************************************************
1128
1133
*/
1129
1134
@@ -1244,6 +1249,48 @@ private boolean _anyIndexed(Collection<POJOPropertyBuilder> props) {
1244
1249
return false ;
1245
1250
}
1246
1251
1252
+ /*
1253
+ /**********************************************************
1254
+ /* Internal methods, conflict resolution
1255
+ /**********************************************************
1256
+ */
1257
+
1258
+ /**
1259
+ * Method that will be given a {@link List} with 2 or more accessors
1260
+ * that may be in conflict: it will need to remove lower-priority accessors
1261
+ * to leave just a single highest-priority accessor to use.
1262
+ * If this succeeds method returns {@code true}, otherwise {@code false}.
1263
+ *<p>
1264
+ * NOTE: method will directly modify given {@code List} directly, regardless
1265
+ * of whether it ultimately succeeds or not.
1266
+ *
1267
+ * @return True if seeming conflict was resolved and there only remains
1268
+ * single accessor
1269
+ */
1270
+ protected boolean _resolveFieldVsGetter (List <AnnotatedMember > accessors ) {
1271
+ do {
1272
+ AnnotatedMember acc1 = accessors .get (0 );
1273
+ AnnotatedMember acc2 = accessors .get (1 );
1274
+
1275
+ if (acc1 instanceof AnnotatedField ) {
1276
+ if (acc2 instanceof AnnotatedMethod ) {
1277
+ // Method has precedence, remove first entry
1278
+ accessors .remove (0 );
1279
+ continue ;
1280
+ }
1281
+ } else if (acc1 instanceof AnnotatedMethod ) {
1282
+ // Method has precedence, remove second entry
1283
+ if (acc2 instanceof AnnotatedField ) {
1284
+ accessors .remove (1 );
1285
+ continue ;
1286
+ }
1287
+ }
1288
+ // Not a field/method pair; fail
1289
+ return false ;
1290
+ } while (accessors .size () > 1 );
1291
+ return true ;
1292
+ }
1293
+
1247
1294
/*
1248
1295
/**********************************************************
1249
1296
/* Internal methods; helpers
0 commit comments