Skip to content

BeanDeserializer does not reset jsonParser currentValue after deserialising nested Object/Collection Node  #1834

@Eoin-Mur

Description

@Eoin-Mur

BeanDeserializer assigns the current value before walking the objects fields.
If the objects fields value is a nested object / collection the deserialiser invoked for these values follows the same pattern invoking setCurrentValue. Similairy any custom serialiser for a field may invoke setCurrentValue.
As the currentValue is not reset after deserialisng the nested object or collection. The parsers current value remains the value of traversed nested object or collection.
This is a issue for any custom serializer which might invoke the getCurrentValue as the value is now out of sync with the currentContext and is pointing to some object outside its tree.

This pattern is used throughout BeanDeserializer and CollectionDeserializer and from the comments introduced via ticket: #631

This is present in the current release 2.9.2

/**
     * Streamlined version that is only used when no "special"
     * features are enabled.
     */
    private final Object vanillaDeserialize(JsonParser p,
    		DeserializationContext ctxt, JsonToken t)
        throws IOException
    {
        final Object bean = _valueInstantiator.createUsingDefault(ctxt);
        // [databind#631]: Assign current value, to be accessible by custom serializers
        p.setCurrentValue(bean);
        if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
            String propName = p.getCurrentName();
            do {
                p.nextToken();
                SettableBeanProperty prop = _beanProperties.find(propName);

                if (prop != null) { // normal case
                    try {
                        prop.deserializeAndSet(p, ctxt, bean);
                    } catch (Exception e) {
                        wrapAndThrow(e, bean, propName, ctxt);
                    }
                    continue;
                }
                handleUnknownVanilla(p, ctxt, bean, propName);
            } while ((propName = p.nextFieldName()) != null);
        }
        return bean;
    }

Example scenario vanillaDeserialize sets the current value as the object walking(ObjA), the field to serialise is an empty ArrayList the deserialiser invoked for example is CollectionDeserializer which follows this patten and sets the current value in the parser as the ArrayList.
CollectionDeserializer returns setting the value of the field in ObjA to the deserialised ArrayList but the parsers current value remains as the ArrayList.

Fix would be in all deserialisers following this pattern to save a reference to the previousValue and before exiting reset the currentValue

@Override
    public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt,
            Collection<Object> result)
        throws IOException
    {
        // Ok: must point to START_ARRAY (or equivalent)
        if (!p.isExpectedStartArrayToken()) {
            return handleNonArray(p, ctxt, result);
        }

        Object prevVal = p.getCurrentValue(); // Keep reference to parents value
        p.setCurrentValue(result);

        JsonDeserializer<Object> valueDes = _valueDeserializer;
        final TypeDeserializer typeDeser = _valueTypeDeserializer;
        CollectionReferringAccumulator referringAccumulator =
            (valueDes.getObjectIdReader() == null) ? null :
                new CollectionReferringAccumulator(_containerType.getContentType().getRawClass(), result);

        JsonToken t;
        while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
            // Process elements
        }
        p.setCurrentValue(prevValue); // reset value to the parent before returning to it
        return result;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    need-test-caseTo work on issue, a reproduction (ideally unit test) needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions