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

Allow @JsonAnySetter on Creator constructors #4366

Draft
wants to merge 35 commits into
base: 2.17
Choose a base branch
from

Conversation

JooHyukKim
Copy link
Member

@JooHyukKim JooHyukKim commented Feb 3, 2024

resolves #562

@JooHyukKim JooHyukKim marked this pull request as draft February 3, 2024 14:39
fieldType = resolveMemberAndTypeAnnotations(ctxt, mutator, fieldType);
keyType = fieldType.getKeyType();
valueType = fieldType.getContentType();
prop = new BeanProperty.Std(PropertyName.construct("stuff"),
Copy link
Member Author

Choose a reason for hiding this comment

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

Shouldnt hard code constructor param name

Comment on lines 185 to 195
AnnotationIntrospector ai = _context.getAnnotationIntrospector();
for (int i = 0; i < props.length; i++) {
SettableBeanProperty prop = props[i];
AnnotatedMember member = prop.getMember();
if (member == null) {
continue;
}
Boolean hasAnySetter = ai.hasAnySetter(member);
if (hasAnySetter == null || !hasAnySetter) {
continue;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Same as '_findCreatorPropWithAnySetter()' method above. Wonder if we can add this method to CreatorProperty class?

_validateNamedPropertyParameter(ctxt, beanDesc, candidate, i,
// [databind#562] Any setter can be used...
Boolean hasAnySetter = ctxt.getAnnotationIntrospector().hasAnySetter(param);
if (hasAnySetter != null && hasAnySetter) {
Copy link
Member

Choose a reason for hiding this comment

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

or if (Boolean.TRUE.equals(hasAnySetter))


// [databind#562]: Respect @JsonAnySetter in @JsonCreator
// check if we have anySetter Param
AnnotationIntrospector ai = _context.getAnnotationIntrospector();
Copy link
Member

Choose a reason for hiding this comment

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

Alas, this is not acceptable from performance perspective: all annotation introspection must occur when constructing deserializers and related handlers. It should be possible to change handling to keep track of information about existence of "any setter", instead of trying to introspect for every deserialization call.

@cowtowncoder
Copy link
Member

Impressive. I am bit hesitant to consider this as one more thing before work on Property Introspection rewrite, but no harm in figuring out how this could work. Added some notes.

@JooHyukKim
Copy link
Member Author

Impressive. I am bit hesitant to consider this as one more thing before work on Property Introspection rewrite,

I concur. And also in the issue #562, this feature is to get included in 3.x.

So I think we can safely consider this feature only after Property Introspection rewrite.

but no harm in figuring out how this could work. Added some notes.

Thankssss! I will keep them updated

@JooHyukKim JooHyukKim changed the title [DRAFT] for #562 feature Allow @JsonAnySetter on Creator constructors Feb 9, 2024
@cowtowncoder
Copy link
Member

Cool, this is much improved. I'll make tiny changes, wrt suggestions I added.

protected Map<Object, Object> initMap(DeserializationContext ctxt)
throws IOException
{
if (_valueInstantiator == null) {
Copy link
Member

Choose a reason for hiding this comment

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

It seems to me that this really should be caught during construction and never get this far?

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved the check accordingly.

@cowtowncoder
Copy link
Member

@JooHyukKim Ok, I made a few changes that I think help, including validation that only one "any-setter" is specified.

I was also wondering if it wouldn't make sense to add knowledge of "any-setter" creator property directly into PropertyValueBuffer (make it take SettableAnyProperty).
Also I think validation wrt DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES need to be able to skip check for placeholder there.

@JooHyukKim
Copy link
Member Author

I was also wondering if it wouldn't make sense to add knowledge of "any-setter" creator property directly into PropertyValueBuffer (make it take SettableAnyProperty).

Do you mean do the PropertyValueBuffer construction with anySetter in it in the first place, in earlier part of _deserializeUsingPropertyBased? If so, sounds like an idea.

Also I think validation wrt DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES need to be able to skip check for placeholder there.

Placeholder? 🤔 Could u elaborate a bit more?

@cowtowncoder
Copy link
Member

I was also wondering if it wouldn't make sense to add knowledge of "any-setter" creator property directly into PropertyValueBuffer (make it take SettableAnyProperty).

Do you mean do the PropertyValueBuffer construction with anySetter in it in the first place, in earlier part of _deserializeUsingPropertyBased? If so, sounds like an idea.

Right.

Also I think validation wrt DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES need to be able to skip check for placeholder there.

Placeholder? 🤔 Could u elaborate a bit more?

What I mean is to test to see that if this setting is enabled, it will not cause failure since property that represents "any-setter" has no associated value.
So by placeholder I meant constructor parameter that is not a "real" parameter, similar to how injectable value isn't required to come from input.

@JooHyukKim
Copy link
Member Author

I was also wondering if it wouldn't make sense to add knowledge of "any-setter" creator property directly into PropertyValueBuffer (make it take SettableAnyProperty).

cc/ @cowtowncoder Implemented as suggested in commit 8612433. Apologies in advance for formatter taking up large portion.

IMO, this new version seems more appropriate in that we don't handle values twice --first buffering in PropertyValueBuffer then transfer to map for AnySetter parameter.

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.

Allow 'JsonAnySetter' to flow through JsonCreator.
2 participants