yasson icon indicating copy to clipboard operation
yasson copied to clipboard

Yasson ignored @JsonbTypeAdapter on field level for map keys

Open mkarg opened this issue 1 year 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.3 inconsistently handles adapters for map keys:

  • Using JsonbConfig::withAdapters, Yasson correctly respects the adapter for a map key.
  • Using @JsonbTypeAdapter on the class field, Yasson incorrectly ignores the adapter for the map key but prints an empty object {} as the key value.

To Reproduce

package de.quipsy.sandbox.yassonbugs;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.adapter.JsonbAdapter;
import jakarta.json.bind.annotation.JsonbTypeAdapter;

public final class YassonBug {

  public static final void main(final String[] arguments) throws IOException {
    final var jsonb = JsonbBuilder.newBuilder().build();
    final var b = new B();
    final var c = new C();
    System.out.println(jsonb.toJson(b)); // correctly prints `{"c":"C"}`
    System.out.println(jsonb.toJson(List.of(b))); // correctly prints `[{"c":"C"}]`
    System.out.println(jsonb.toJson(Map.of(c, b))); // prints `[{"key":{},"value":{"c":"C"}}]`, but should print `[{"key":{"c"},"value":{"c":"C"}}]`
  }

  public static final class B {
    @JsonbTypeAdapter(CAdapter.class)
    public final C c = new C();
  }

  public static final class C {
    @Override
    public final String toString() {
      return "C";
    }
  }

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

    @Override
    public final String adaptToJson(final C obj) throws Exception {
      return obj.toString();
    }

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

  }

}

Expected behavior

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

NB: Yasson should also respect adapter registered using @JsonbTypeAdapter at the class level for map key, just as it already correctly respects that adapter for any other use besides map key.

System information:

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

Additional context

N/A

mkarg avatar May 11 '23 07:05 mkarg