jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

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

Open liang-shen opened this issue 1 year ago • 5 comments

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.

liang-shen avatar Aug 02 '22 03:08 liang-shen

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.

yawkat avatar Aug 02 '22 10:08 yawkat

@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.

cowtowncoder avatar Aug 02 '22 20:08 cowtowncoder

@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 avatar Aug 03 '22 00:08 liang-shen

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

liang-shen avatar Aug 03 '22 00:08 liang-shen

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

yawkat avatar Aug 03 '22 08:08 yawkat

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<ObjectXX>

@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; }

wjtest-wj avatar Mar 30 '23 03:03 wjtest-wj

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.

cowtowncoder avatar Mar 31 '23 02:03 cowtowncoder