@@ -251,9 +251,11 @@ public AnnotatedMember getJsonKeyAccessor() {
251251 // If @JsonKey defined, must have a single one
252252 if (_jsonKeyAccessors != null ) {
253253 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+ }
257259 }
258260 // otherwise we won't greatly care
259261 return _jsonKeyAccessors .get (0 );
@@ -270,11 +272,14 @@ public AnnotatedMember getJsonValueAccessor()
270272 collectAll ();
271273 }
272274 // If @JsonValue defined, must have a single one
275+ // 15-Jan-2023, tatu: Except let's try resolving "getter-over-field" case at least
273276 if (_jsonValueAccessors != null ) {
274277 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+ }
278283 }
279284 // otherwise we won't greatly care
280285 return _jsonValueAccessors .get (0 );
@@ -1123,7 +1128,7 @@ protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
11231128
11241129 /*
11251130 /**********************************************************
1126- /* Overridable internal methods, sorting, other stuff
1131+ /* Internal methods, sorting
11271132 /**********************************************************
11281133 */
11291134
@@ -1244,6 +1249,48 @@ private boolean _anyIndexed(Collection<POJOPropertyBuilder> props) {
12441249 return false ;
12451250 }
12461251
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+
12471294 /*
12481295 /**********************************************************
12491296 /* Internal methods; helpers
0 commit comments