yasson icon indicating copy to clipboard operation
yasson copied to clipboard

Yasson ignores @JsonbTypeAdapter on class level of object in Collection

Open mkarg opened this issue 11 months ago • 0 comments

Describe the bug

According to the JSON-B Specification v3 chapter 4.7.1...

There are two ways how to register JsonbAdapter:

  • Using JsonbConfig::withAdapters method;
  • Annotating a class field with JsonbTypeAdapter annotation.

Yasson 3.0.4 inconsistently handles adapters for objects in collections:

  • Using JsonbConfig::withAdapters, Yasson correctly respects the adapter for an object in a collection.
  • Using @JsonbTypeAdapter on the class, Yasson incorrectly ignores the adapter for an object in a collection but serializes the object's public fields instead.

To Reproduce

public class YassonBug {

  public static void main(String[] arguments) throws Exception {
    var c = new C();

    // Correctly applies @JsonbTypeAdapter in both cases
    try (var jsonb = JsonbBuilder.newBuilder().build()) {
      System.out.println(jsonb.toJson(c)); // correctly prints `"correct value"`
      System.out.println(jsonb.toJson(Set.of(c))); // correctly prints `["correct value"]`
    }

    // Correctly applies config in both cases
    var config = new JsonbConfig().withAdapters(new CAdapter());
    try (var jsonb = JsonbBuilder.newBuilder().withConfig(config).build()) {
      System.out.println(jsonb.toJson(Set.of(c))); // correctly prints `["correct value"]`
      System.out.println(jsonb.toJson(c)); // correctly prints `"correct value"`
    }

    // Incorrectly applies @JsonbTypeAdapter in the `List.of(c)` case (and remembers wrong decision in the `c` case)
    try (var jsonb = JsonbBuilder.newBuilder().build()) {
      System.out.println(jsonb.toJson(Set.of(c))); // incorrectly prints `[{"wrong":"value"}]`, should be `["correct value"]`
      System.out.println(jsonb.toJson(c)); // incorrectly prints `{"wrong":"value"}`, should be `"correct value"`
    }
  }

  @JsonbTypeAdapter(CAdapter.class)
  public static class C {
    public String wrong = "value"; 
  }

  public static class CAdapter implements JsonbAdapter<C, String> {

    @Override
    public String adaptToJson(C obj) throws Exception {
      return "correct value";
    }

    @Override
    public C adaptFromJson(String obj) throws Exception {
      throw new UnsupportedOperationException("Unimplemented method 'adaptFromJson'");
    }

  }

}

Expected behavior

Yasson should correctly respect adapter for object in collection registered using @JsonbTypeAdapter just in the same ways it already correctly respects adapters set using ::withAdapters.

System information:

  • OS: Windows
  • Java Version: 19
  • Yasson Version: 3.0.4

Additional context

See also https://github.com/eclipse-ee4j/yasson/issues/603.

mkarg avatar Oct 30 '24 16:10 mkarg