Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StringCollectionSerializer calls JsonGenerator.setCurrentValue(value), which messes up current value for sibling properties #2475

Closed
bohnman opened this issue Sep 26, 2019 · 5 comments
Milestone

Comments

@bohnman
Copy link

bohnman commented Sep 26, 2019

Versions: 2.9.9 and 2.10.0.pr3

Given the following class definition:

public static class Item {
        private Collection<String> set;
        private String id;

        public Item(String id) {
            this.set = new HashSet<>();
            this.id = id;
        }

        public Collection<String> getSet() {
            return set;
        }

        public String getId() {
            return id;
        }
    }

You'll notice that when the serializer writes out the set and id properties, the current value on jgen is HashSet not the Item. I write a Jackson filtering library and I count on the current value being correct.

Doing some digging, I noticed that the StringCollectionSerializer sets the currentValue in the serialize method like so:

@Override
    public void serialize(Collection<String> value, JsonGenerator g,
            SerializerProvider provider) throws IOException
    {
        g.setCurrentValue(value);
        final int len = value.size();
        if (len == 1) {
            if (((_unwrapSingle == null) &&
                    provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
                    || (_unwrapSingle == Boolean.TRUE)) {
                serializeContents(value, g, provider);
                return;
            }
        }
        g.writeStartArray(len);
        serializeContents(value, g, provider);
        g.writeEndArray();
    }

However, the current value is not explicity set in IndexedStringListSerializer nor CollectionSerializer, and consequently they both don't exhibit this problem

I have attached a java class that exhibits this behavior as long as you're using Jackson version 2.9.9 or later
Test.java.zip

@cowtowncoder cowtowncoder changed the title StringCollectionSerializer calls jgen.setCurrentValue(value), which messes up current value for sibling properties StringCollectionSerializer calls JsonGenerator.setCurrentValue(value), which messes up current value for sibling properties Sep 27, 2019
@cowtowncoder
Copy link
Member

Thank you for reporting the issue. Sounds like a bug.

Since 2.10.0 is now being released (and 2.10.0.pr3 having been available), it would be interesting to see if there is any change in behavior: I hope to add a unit test once I have time to investigate this.

@cowtowncoder
Copy link
Member

Ok. I must admit I am not sure I fully follow what would be the expected behavior here, at every given point. I can see there is a discrepancy, but I am not sure which serializers are doing the right thing. Perhaps StringCollectionSerializer is calling method too early (and should do it after writeStartArray()? Conversely it seems that other serializer(s) are missing needed call...

@cowtowncoder
Copy link
Member

Yes, I think call needs to be right after writeStartArray(), to nest as expected. "current value" is, I think, more accurately "current structured value" I guess...

@bohnman
Copy link
Author

bohnman commented Sep 29, 2019

@cowtowncoder Can the call to setCurrentValue be moved to serializeContents? This is what IndexedStringListSerializer and CollectionSerializer do. I agree that it needs to be after writeStartArray because that call creates a new context just for the array and doesn't overwrite the current context for the array's "parent", which in my example is Item

@cowtowncoder
Copy link
Member

I think I'll just start using new (in 2.10) writeStartArray() methods that will do setting.

My main concern is adding unit tests to try to sort of define expected behavior: the whole "current value" concept is (alas) quite undefined; so while fix itself looks easy enough, it'd be good to both find other cases (I'm sure they exist) and to guard against otherwise possible regressions from refactoring.

@cowtowncoder cowtowncoder added this to the 2.10.1 milestone Sep 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants