diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java index d606d86101..df012fbe59 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java @@ -538,7 +538,7 @@ protected void _set(Object instance, Object propName, Object value) public int getParameterIndex() { return _parameterIndex; } @Override - public Object createParameterObject() { return new HashMap<>(); } + public Object createParameterObject() { return new LinkedHashMap<>(); } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index db68167e5a..48f3941ad7 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -237,21 +237,34 @@ public Object[] getParameters(SettableBeanProperty[] props) private Object _createAndSetAnySetterValue() throws JsonMappingException { Object anySetterParameterObject = _anyParamSetter.createParameterObject(); - for (PropertyValue pv = _anyParamBuffered; pv != null; pv = pv.next) { - try { - pv.setValue(anySetterParameterObject); - - // Since one of callers only exposes JsonMappingException, but pv.setValue() - // nominally leaks IOException, need to do this unfortunate conversion - } catch (JsonMappingException e) { - throw e; - } catch (IOException e) { - throw JsonMappingException.fromUnexpectedIOE(e); - } - } + + // Since setter values are stored in a reverse-order linked list, + // this will set them in their original order + _setSetterValuesInReverse(_anyParamBuffered, anySetterParameterObject); return anySetterParameterObject; } + private static void _setSetterValuesInReverse(PropertyValue pv, Object anySetterParameterObject) + throws JsonMappingException + { + if (pv == null) { + return; + } + + _setSetterValuesInReverse(pv.next, anySetterParameterObject); + + try { + pv.setValue(anySetterParameterObject); + + // Since one of callers only exposes JsonMappingException, but pv.setValue() + // nominally leaks IOException, need to do this unfortunate conversion + } catch (JsonMappingException e) { + throw e; + } catch (IOException e) { + throw JsonMappingException.fromUnexpectedIOE(e); + } + } + protected Object _findMissing(SettableBeanProperty prop) throws JsonMappingException { // 08-Jun-2024: [databind#562] AnySetters are bit special diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/AnySetterForCreator562Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/AnySetterForCreator562Test.java index e18cc44fd8..33c812079f 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/AnySetterForCreator562Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/AnySetterForCreator562Test.java @@ -182,7 +182,7 @@ public void testNodeAnySetterViaCreator562() throws Exception PojoWithNodeAnySetter.class); assertEquals("value", pojo.a); - assertEquals(a2q("{'c':111,'b':42}"), pojo.anySetterNode + ""); + assertEquals(a2q("{'b':42,'c':111}"), pojo.anySetterNode + ""); // Also ok to get nothing, resulting in empty ObjectNode pojo = MAPPER.readValue(a2q("{'a':'ok'}"), PojoWithNodeAnySetter.class);