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

Support @JsonIgnoreProperties to work with @JsonValue #4070

Merged
merged 13 commits into from
Oct 1, 2023

Conversation

JooHyukKim
Copy link
Member

relates #3647 .

@@ -254,6 +258,20 @@ public void serialize(Object bean, JsonGenerator gen, SerializerProvider ctxt) t
}
}

private JsonSerializer<Object> _updateserWithIgnorals(JsonSerializer<Object> ser, SerializerProvider ctxt) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method "hypothetically" lazy initializes a serializer with @JsonIgnoreProperties applied. Only because at line 248

ser = _findDynamicSerializer(ctxt, value.getClass());

... is called, at least for our failing-test. We need to figure out how to make the serializer final 🤔

@JooHyukKim JooHyukKim closed this Aug 12, 2023
@JooHyukKim
Copy link
Member Author

Closed for now. I am not sure if current version takes right approach.

@cowtowncoder
Copy link
Member

I think this is a good approach in principle. There may be some edge cases -- like, should the new set of ignored properties replace what might already exist or combine it with union (I suspect union is the right thing to do).
This would occur if value class itself has @JsonIgnoreProperties and then @JsonValue annotated method adds more.

Also: not sure if you already saw it, but BeanDeserializerBase does have withIgnorableProperties to sort of implement this for embedded properties. Maybe that could help implementation here.

@JooHyukKim
Copy link
Member Author

JooHyukKim commented Aug 19, 2023

I think this is a good approach in principle.

I see. My concern was with timing, because with current revision we are detecting ignorals lazily in _findDynamicSerializer(). It might be reasonable after all for it being "Dynamic" 🤔.

There may be some edge cases -- like, should the new set of ignored properties replace what might already exist or combine it with union (I suspect union is the right thing to do).

Will try to include tests for such edge cases.

Thank you for explanation! 👍🏻

@JooHyukKim JooHyukKim reopened this Aug 19, 2023
@JooHyukKim JooHyukKim marked this pull request as ready for review August 19, 2023 15:57
@JooHyukKim JooHyukKim closed this Sep 5, 2023
@JooHyukKim JooHyukKim deleted the 3647- branch September 5, 2023 23:34
@JooHyukKim JooHyukKim restored the 3647- branch September 5, 2023 23:36
@JooHyukKim JooHyukKim deleted the 3647- branch September 5, 2023 23:38
@JooHyukKim JooHyukKim restored the 3647- branch September 5, 2023 23:53
@JooHyukKim
Copy link
Member Author

Accidentally closed 😅

@JooHyukKim JooHyukKim reopened this Sep 5, 2023
@@ -126,6 +126,11 @@ protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties,
return new BeanSerializer(this, properties, filteredProperties);
}

@Override // @since 2.16
public JsonSerializer<?> withIgnoredProperties(Set<String> toIgnore) {
return new BeanSerializer(this, toIgnore, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern here is that passing null could remove effects of possible @JsonIncludeProperties. But looking at BeanSerializerBase, this information is not really retained explicitly -- but hopefully src._filteredProps has information.

So this is why having those tests is good verification.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is why having those tests is good verification.

True true, Makes sense 👌🏽

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe pass empty Set<> instead? Whichever keeps codebase consistent, that's why I somehow thought passing 'null' was the way to go

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, no, null is fine (wrt empty). I was thinking out aloud that originally provided inclusion cannot be passed again (which would come from @JsonIncludeProperties).

But let's worry about this if someone can figure out case where this is problematic.

@cowtowncoder cowtowncoder merged commit ae77a0c into FasterXML:2.16 Oct 1, 2023
3 checks passed
@cowtowncoder
Copy link
Member

Ok, merging to master is challenging here... but I'll get it done.

One thing I realized after merging, however, is that I think that possible Set<String> of ignored properties should probably obtained from within createContextual() and then used when actually constructing JsonSerializer. This avoids having to call AnnotationIntrospector multiple times.

Another thing: I wonder if making value class final would make things fail since different call path is used (serializer can be fetched eagerly).

Anyway I'll work on merge now, almost done.

// [databind#3647] : Support @JsonIgnoreProperties to work with @JsonValue
public class JsonValueIgnore3647Test extends BaseMapTest
{
static class Foo3647 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JooHyukKim Making this final will make test fail. I think this is because _valueSerializer has then been pre-fetched.... so fix here won't work for all cases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I chose where fix is currently is (JsonValueSerializer.dynamicSerializer()) because of dynamically fetched types such as List in mind🤔

I think we can fix this either with reverting current change or just on top of this one. (Later in the evening, its 12nn atm)

@JooHyukKim
Copy link
Member Author

should probably obtained from within createContextual() and then used when actually constructing JsonSerializer. This avoids having to call AnnotationIntrospector multiple times.

I recall trying to apply fix at 'creatContexual' and failed because not enough information or something. You think it's possible?

@cowtowncoder
Copy link
Member

@JooHyukKim it's not either-or but both -- in static (final) case has to be done in createContextual(), in dynamic case in the place it's done now. I can try to see if I can do that change.

@JooHyukKim
Copy link
Member Author

it's not either-or but both

I see, I thought there may be a common and reasonable call path for both case. Thank you for helping out🙏🙏

@cowtowncoder
Copy link
Member

Hmmh. Looking at code, I think that Set<String> can and should actually be fetched right when constructing JsonValueSerializer: maybe adding a factory method for constructing instance, passing necessary config or context.
And then apply if non-empty Set, wherever JsonSerializer being delegated to is fetched.

Let me see if I can get anything further done...

@JooHyukKim JooHyukKim deleted the 3647- branch October 1, 2023 13:51
@cowtowncoder
Copy link
Member

@JooHyukKim I got it all working, I think. Including 3.0 where code had been refactored (and JsonValueSerializer implementation has diverged).

@JooHyukKim
Copy link
Member Author

@cowtowncoder Phew, great! I saw commit messages in master branch and also did some research via #4134.

Quick question: Are refactoring works welcome in master branch now? Considering 2.16-rc is coming soon, I thought it would be effective point in time to prepare for 3.0 and such. My scope will cover non-intrusive refactors or increase test coverage.

@JooHyukKim
Copy link
Member Author

My scope will cover non-intrusive refactors or increase test coverage.

Thinking now, maybe some other that I don't know of 😆

@cowtowncoder
Copy link
Member

Yes. On test coverage, I hope we could reduce amount of test code without reducing test coverage: since test code is code to maintain just like regular code, over time there's more baggage. So new test code needs to be meaningful and not just to increase metrics -- I am not a big fan of coverage metrics just because it sometimes leads to "silly" tests that have more code than existing in non-test code being covered.

On refactoring, reducing amount of code (without adding overhead) would be welcome as well.

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

Successfully merging this pull request may close these issues.

2 participants