FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.53k stars 1.38k forks source link

BeanDeserializerBase::_replaceProperty() should not locate the props index using object from another array #3562

Open liang-shen opened 2 years ago

liang-shen commented 2 years ago

Describe the bug BeanDeserializerBase::resolve(DeserializationContext ctxt) will replace the "creatorProps" props using contextualize props. But the "SettableBeanProperty origProp" is from "_beanProperties". The "creatorProps" is created as

creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());

Version information 2.13.3

To Reproduce The second property "expireTime" is two different object in "creatorProps" & "_beanProperties"

image

Expected behavior May consider to compare the property name string instead of the props object.

Additional context This is encountered in Micronaut framework.

yawkat commented 2 years ago

i dont understand the issue, can you give a test case? Also without micronaut please, since we introduce our own modifications to bean scanning in micronaut.

cowtowncoder commented 2 years ago

@liang-shen That's an implementation detail, and not a direct bug. So there needs to be some problem to solve to suggest a change in implementation just like @yawkat said.

liang-shen commented 2 years ago

@yawkat the issue is the parameter "origProp" is from "_beanProperties". the "creatorProps" is another new array. So when try to locate the element using " if (creatorProps[i] == origProp)", it will always fail.

Then the "_beanProperties" will get the contextualized "newProp". But the "creatorProps" will always original one.


protected void _replaceProperty(BeanPropertyMap props, SettableBeanProperty[] creatorProps,
            SettableBeanProperty origProp, SettableBeanProperty newProp)
    {
        props.replace(origProp, newProp);
        // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
        if (creatorProps != null) {
            // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
            //   fully count on this? May need to revisit in future; seems to hold for now.
            for (int i = 0, len = creatorProps.length; i < len; ++i) {
                if (creatorProps[i] == origProp) {
                    creatorProps[i] = newProp;
                    return;
                }
            }
            /*
            // ... as per above, it is possible we'd need to add this as fallback
            // if (but only if) identity check fails?
            for (int i = 0, len = creatorProps.length; i < len; ++i) {
                if (creatorProps[i].getName().equals(origProp.getName())) {
                    creatorProps[i] = newProp;
                    return;
                }
            }
            */
        }
    }
liang-shen commented 2 years ago

_replaceProperty() assume the "_beanProperties" and "creatorProps" contains exactly same array of "SettableBeanProperty". In my case, it is not true

yawkat commented 2 years ago

@liang-shen i can understand your description, but please give an example where this is actually problematic.

wjtest-wj commented 1 year ago

I finded lombok @Builder annotation and @JsonFormat annotation will caused @JsonFormat not valid. I debuged and finded the reason is here. _beanProperties replaced success and creatorProps replaced fail

for you reference

the object is List

@Builder @Getter @Setter @ToString ObjectXX { @ApiModelProperty("创建时间(格式:yyyy-MM-dd HH:mm:ss)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createdTime; }

cowtowncoder commented 1 year ago

Unfortunately this does not help: for one it requires Lombok, but it is also not an actual test.

No further help can be given without something more concrete.