Open zman0900 opened 1 year ago
I wonder if this fails against latest 2.15.0-SNAPSHOT
-- there are a few improvements to Record
handling that might solve this issue.
Lombok case may be different: it all depends on how Lombok pre-processes class definitions; although I think POJOs will generally require use of @JsonCreator
except in limited special cases such as (one of?) parameters annotated with @JsonProperty
(which triggers auto-detection). But even that requires that there are no other possibly competing constructors.
So basically this would be two separate (but related) issues: whether this works for Records (it should), and for POJOs (likely not as there is no definition of "canonical constructor" nor necessarily parameter names).
I also tried with the de-lomboked version (private final fields, getters, single constructor) and saw the same behavior - had to add @JsonCreator
to the constructor. In all cases, it worked fine without @JsonCreator
when maybeNumber
was just a String field with no annotation, and it did seem like adding @JsonDeserialize(using = ...)
to it was working too.
I changed the title here to refer to just Records: separate one would be needed for POJOs. Or alternatively may change this to refer to POJOs, file new one for Records if issue is still reproducible. Two cases need to be dealt with separately I think.
With the renamed title, it now becomes duplicate of #3297?
@yihtserns Which is, I think, fixed? But yes, will close as duplicate.
EDIT: Actually, will hold off not closing yet.
@zman0900 There has been a major update with #3724 -- if you have any way to test your code against 2.15.0-SNAPSHOT (either built locally, or from Sonatype Snapshot repo), it'd be good to see if your use case might now work too. It should, I think, as Record constructor discovery was improved significantly.
Which is, I think, fixed? But yes, will close as duplicate.
Yupe I've tested with com.fasterxml.jackson.core:jackson-databind:2.15.0-SNAPSHOT
from https://oss.sonatype.org/content/repositories/snapshots, and it worked.
But yeah @zman0900 can also verify that it works on his side, before closing this.
@zman0900 about the issue with Lombok, I think you should create another issue for that discussion as suggested because something weird and very different is going on over there.
Please drop the link here once you've created it, so I can also include what I've discovered so far. (been long enough that I've forgotten what I've discovered).
Hello! I am actually facing this issue when used in conjunction @JsonAlias
. For example, with:
@JsonAlias("isApp")
@JsonDeserialize(converter = StringToBooleanConverter.class)
boolean due
I receive the following exception:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `boolean` from String "0": only "true"/"True"/"TRUE" or "false"/"False"/"FALSE" recognized
When I use @JsonProperty
instead of @JsonAlias
, it works fine. I am using jackson-databind 2.14.2. When I use the 2.15.0 RC, I get some weird exceptions:
java.lang.NoSuchMethodError: 'com.fasterxml.jackson.core.StreamReadConstraints com.fasterxml.jackson.core.JsonParser.streamReadConstraints()'
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer.deserialize(NumberDeserializers.java:1037) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer.deserialize(NumberDeserializers.java:976) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:568) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:568) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:568) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:2105) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1481) ~[jackson-databind-2.15.0-rc2.jar:2.15.0-rc2]
at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:204) ~[spring-web-6.0.7.jar:6.0.7]
at org.springframework.http.codec.json.AbstractJackson2Decoder.lambda$decodeToMono$2(AbstractJackson2Decoder.java:189) ~[spring-web-6.0.7.jar:6.0.7]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:132) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2071) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.5.4.jar:3.5.4]
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:415) ~[reactor-netty-core-1.1.5.jar:1.1.5]
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:431) ~[reactor-netty-core-1.1.5.jar:1.1.5]
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:485) ~[reactor-netty-core-1.1.5.jar:1.1.5]
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:712) ~[reactor-netty-http-1.1.5.jar:1.1.5]
To add some context, the API I am using returns 0
for false
and 1
for true
. I'd like to map that to a boolean
, hence my use of a converter. Not sure if there is a better way to do this currently in Jackson.
@lbkulinski I'm not able to reproduce your issue when using 2.15.0-rc1
nor 2.15.0-rc2
.
I recommend that you create a new issue, together with a sample Github repo that reproduces that issue.
@lbkulinski I'm not able to reproduce your issue when using
2.15.0-rc1
nor2.15.0-rc2
.I recommend that you create a new issue, together with a sample Github repo that reproduces that issue.
Will do. Thanks!
@lbkulinski (From a quick glance, I suspect that error is due to version of jackson-core
not matching version of jackson-databind
, e.g. you're using jackson-databind:2.15.0-rc1
with jackson-core:2.14.2
)
Yes, that exceptions is due to mismatch: jackson-databind
2.15 depends on some new features of jackson-core
2.14 (reverse would typically not be a problem -- databind 2.14 would work with core 2.15, but it is recommended to match minor versions of all components for simplicity).
Yep. That was it! I had just been using jackson-core
from spring-boot-starter-parent
. Thanks all!
Describe the bug When annotation like
@JsonDeserialize(converter = MyConverter.class)
is applied to a component of a Record or to a field of an immutable class (such as lombok @Value or just plain class with final fields, all-args constructor, and only getters), it seems the Converter is not actually used unless@JsonCreator
is also present on the constructor.Version information Jackson Databind 2.14.1 (with parameter names module) Java 17
To Reproduce Given converter class like:
And some JSON like this:
I believe Jackson should be able to bind this Record:
Or bind this class:
But these lead to errors like:
Adding a compact constructor to the Record (or explicit all-args constructor to the class) that is annotated with
@JsonCreator
works around this.I don't believe this should be necessary, as using custom deserializer like
@JsonDeserialize(using = MyDeserializer.class)
seems to work fine without it.