-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Change Records deserialization to use the same mechanism as POJO deserialization. #3724
Change Records deserialization to use the same mechanism as POJO deserialization. #3724
Conversation
src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
Show resolved
Hide resolved
public static AnnotatedConstructor findRecordConstructor(DeserializationContext ctxt, | ||
BeanDescription beanDesc, List<String> names) { | ||
return new CreatorLocator(ctxt, beanDesc) | ||
public static AnnotatedConstructor findRecordConstructor(AnnotatedClass recordClass, AnnotationIntrospector intr, MapperConfig<?> config, List<String> names) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API change? Possibly not a good thing - any chance that the old version can be kept and deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah no, please leave the signature as it was: DeserializationContext
and BeanDescription
can be used to access AnnotationIntrospector
and MapperConfig
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API change? Possibly not a good thing - any chance that the old version can be kept and deprecated?
Done - added a new method while keeping (but not deprecating) the old method.
Yeah no, please leave the signature as it was: DeserializationContext and BeanDescription can be used to access AnnotationIntrospector and MapperConfig.
The problem is in the place I'm using it now (POJOPropertiesCollector
), I don't have DeserializationContext
nor BeanDescription
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, ok that makes sense. But that's bit of a problem. Let me think about it.
src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
Outdated
Show resolved
Hide resolved
First of all, thank you for contributing this @yihtserns ! It sounds like solid improvement, potentially. I added some smaller notes on keeping existing API in some places, but there is one bigger request I have: this PR needs to be against |
Do I put "since 2.15" in the deprecation notice? And yeah I wasn't sure whether I should go with 2.14 or 2.15 since https://github.com/FasterXML/jackson/blob/master/CONTRIBUTING.md didn't mention the latter... That doc needs to be updated? |
698e248
to
bb2ba45
Compare
9a69ce8
to
1ca9b17
Compare
Yes.
Thanks, I'll need to update that. There are some things that should go into earlier branches too -- generally earliest maintained, for safe enough fixes. So it is not easy to correctly guess what I think is the right branch :) |
@@ -467,6 +467,10 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri | |||
// regular property? needs buffering | |||
SettableBeanProperty prop = _beanProperties.find(propName); | |||
if (prop != null) { | |||
if (prop.isIgnorable() && _beanType.isRecordType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there a problem here, to require additional processing? And/or would this work even for POJO types?
src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
Outdated
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java
Show resolved
Hide resolved
Ok, looks pretty good. I do need to go over it again with more thought, but I like how small changes are. |
1ca9b17
to
2c15147
Compare
@yihtserns One more thing: I hope to be able to merge this soon. One last thing before that is that we need a Contributor License Agreement (CLA) before merging the first contribution. This only needs to be done once and then it is good for all future PRs for Jackson project. Document is here: https://github.com/FasterXML/jackson/blob/master/contributor-agreement.pdf and the usual way is to print, fill & sign, scan/photo, email to Thank you again for providing this patch -- looking forward to merging it! |
I'm currently re-reviewing if UPDATE: Didn't manage to find a low-change way, so decided to stick with this approach (with some difference) + smothered it with docs. |
2c15147
to
3d6c6cf
Compare
CLA sent. |
3d6c6cf
to
eaf013a
Compare
@leonardehrenfried that symptom sounds similar to the one describe in #3628 (comment) - let me test that. |
@leonardehrenfried so I tested
I've confirmed that the issue you're facing is related to the broken workaround mentioned in #3628, unrelated to this change. |
I since checked and we seem to be using a custom object mapper in the test:
So it appears that your analysis is totally correct. I'm still not clear if this is was an intentional change in Jackson or not - can you clarify this for me? Asked the other way around: is the old behaviour going to be restored and I should just wait for a new release or do I need to change the config of my object mapper? |
I think that config was used because you had the same problem as #3628, and I can't think of an alternative solution for that problem.
I've helped create #3894 to support that type of config. |
This is why we publish release candidates -- 2.15.0-rc1, rc2, rc3 -- to try to get users to verify if they find any regressions beyond what our unit test suite catches. Nothing was reported for this. Now, I don't know what tests you have so I cannot say if behavior is expected or not: sometimes usage is based on undefined behavior, in which case change may be intended (typically due to a fix to some known problem, and change to unsupported case incidental). Thank you for helping create a new issue. We'll see where that leads. |
I'm sorry and as an open source maintainer myself I feel you. I'm the last guy showing up on an issue making demands. I would love to help diagnose and test and don't expect you to make a potentially broken config work for my benefit. |
@leonardehrenfried Oh and just to make sure: I did not mean to blame you or users at all. I appreciate your reaching out and reporting the issue. I think we can figure this out; PR submitted might be the way, although I have some reservations. But it's a tricky problem. |
@leonardehrenfried I've spent a bit of time to study your codebase to understand why that config was used - seems like it was to prevent I assume that is to make assertion easier, since that method returns non-constant number? If that's the case, here's my suggestion (tested with public abstract class SnapshotTestBase {
...
private static class SnapshotItinerarySerializer implements SnapshotSerializer {
private SnapshotItinerarySerializer() {
...
// Remove this config:
//objectMapper.setVisibility(
// objectMapper
// .getSerializationConfig()
// .getDefaultVisibilityChecker()
// .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
// .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
// .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
// .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
//);
// Add this:
objectMapper.addMixIn(ApiLeg.class, ApiLegMixin.class);
...
}
}
/**
* To exclude {@link ApiLeg#getDuration()} from being deserialized because the returned number
* is non-constant making it impossible to assert.
*/
private abstract static class ApiLegMixin {
@JsonIgnore
abstract double getDuration();
}
} |
@yihtserns thanks so much for this. It absolutely fixes the problems we are having. Fantastic work! |
Related to #3900 |
Another breakage: #3938. |
I used to think "nobody would ever put a setter in a Record since nothing is mutable, right?" Now I know how ignorant I was... |
To be honest, that use case is a bit "Creative" and just used to prevent deserialization of something without full ignoral. If someone else has shown that use case to me, I might have argued against it tho, with Records. Given that they are immutable. Anyway, was happy to figure out how to make it work again via fix for #3928. |
Caused #3968. |
New
@JsonCreator.mode=DISABLED
on canonical constructor.@JsonCreator
annotation) non-canonical constructor when 1/more of its parameter is/are annotated with@JsonProperty
.@JsonCreator
annotation) 1-arg delegating constructor.@JsonCreator
annotation) 1-arg delegating factory method.@JsonCreator
annotation) constructor/factory method detection viaMapperFeature.AUTO_DETECT_CREATORS
.This is a non-exhaustive list - I don't have full knowledge of existing JavaBeans deserialization capabilities.
Fixes
@JsonSetter
does not work withjava.lang.Record
#2974@JsonNaming
does not work with Records #2992@JsonCreator
annotation on record classes #3180 (via "implicit" 1-arg delegating constructor/factory method)@JsonDeserialize(converter = ...)
does not work with Records #3297JsonTypeInfo.As.EXTERNAL_PROPERTY
does not work with record wrappers #3342