yasson icon indicating copy to clipboard operation
yasson copied to clipboard

@JsonbTypeAdapter recognized but not used for record classes

Open bmarwell opened this issue 2 years ago • 2 comments

Describe the bug

record MyClass(@JsonbProperty("my_set_field") @JsonbTypeAdapter(SetAdapter.class) Set<String> entries) {};

public class SetAdapter implements JsonbAdapter<String, Set<String>> { /* ... */ }

Exception:

Caused by: jakarta.json.bind.JsonbException: Adapter of runtime type class java.lang.String does not match property type interface java.util.Set
        at [email protected]/org.eclipse.yasson.internal.AnnotationIntrospector.getAdapterBindingFromAnnotation(AnnotationIntrospector.java:247)
        at [email protected]/org.eclipse.yasson.internal.AnnotationIntrospector.getAdapterBinding(AnnotationIntrospector.java:221)
        at [email protected]/org.eclipse.yasson.internal.model.PropertyModel.introspectCustomization(PropertyModel.java:272)
        at [email protected]/org.eclipse.yasson.internal.model.PropertyModel.<init>(PropertyModel.java:171)
        at [email protected]/org.eclipse.yasson.internal.ClassParser.lambda$parseProperties$0(ClassParser.java:70)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1787)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at [email protected]/org.eclipse.yasson.internal.ClassParser.parseProperties(ClassParser.java:71)
        at [email protected]/org.eclipse.yasson.internal.MappingContext.lambda$createParseClassModelFunction$1(MappingContext.java:97)
        at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1740)
        at [email protected]/org.eclipse.yasson.internal.MappingContext.getOrCreateClassModel(MappingContext.java:81)
        at [email protected]/org.eclipse.yasson.internal.Unmarshaller.deserializeItem(Unmarshaller.java:60)
        at [email protected]/org.eclipse.yasson.internal.Unmarshaller.deserialize(Unmarshaller.java:51)
        at [email protected]/org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:59)
        at [email protected]/org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:66)

To Reproduce

See classes above

Expected behavior

The 2nd parameter is used for comparison as it is for POJOs.

System information:

  • OS: Mac
  • Java Version: 17, 20
  • Yasson Version: 2.0.4

Additional context

./.

bmarwell avatar Jul 10 '23 15:07 bmarwell

I found out that neither

public class SetAdapter implements JsonbAdapter<Set<String>, JsonString> {}

and

public class SetAdapter implements JsonbAdapter<Set<String>, String> {}

Now that error is gone, but neither option was actually called.

bmarwell avatar Jul 11 '23 06:07 bmarwell

I found an issue that seems to have exactly the same cause. It works if Yasson first sees the record class directly with the adapter, before it sees it in a generic type.

I've created a very minimalistic reproducer here. If you want, I can turn that into a test for a PR. Finding and fixing the actual bug would require diving deeper into the Yasson code than I can find the time for.

t1 avatar Oct 16 '24 06:10 t1