yasson icon indicating copy to clipboard operation
yasson copied to clipboard

Map<K, V> produces JSON list instead of JSON map

Open mkarg opened this issue 1 year ago • 1 comments

Describe the bug

According to JSON-B Specification v3 chapter 3.1.1 all implementations MUST support serialization of java.util.Map. While Yasson does serialize maps, it does it in an inconsistent way:

  • Map<String, V> is correctly serialized as a JSON map where String is key and serialized V is value.
    System.out.println(jsonb.toJson(Map.of(k.toString(), v))); // correctly prints `{"k":<v>}`
    
  • Map<K, V> is rather unexpectedly serialized as a JSON list holding one JSON map per entry inside that list, all having a key name of literally the word key, and a value of literally the word value.
    System.out.println(jsonb.toJson(Map.of(k, v))); // prints `[{"key":<k>,"value":<v>}]`, but should print `{<k>: <v>}`
    

To Reproduce

package de.quipsy.sandbox.yassonbugs;

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

import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import jakarta.json.bind.adapter.JsonbAdapter;

public final class YassonBugs {

  public static final void main(final String[] arguments) throws IOException {
    final var cfg = new JsonbConfig().withAdapters(new CAdapter());
    final var jsonb = JsonbBuilder.newBuilder().withConfig(cfg).build();
    final var k = new C();
    final var v = new C();
    System.out.println(jsonb.toJson(Map.of(k.toString(), v))); // correctly prints `{"C":"C"}]`
    System.out.println(jsonb.toJson(Map.of(k, v))); // prints `[{"key":"C","value":"C"}]`, but should print `{"C": "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 System.out.println(jsonb.toJson(Map.of(k, v))); should print print {<k>: <v>}, i. e. a map with serialized k as key and serialized v as value, to be consistent with the behaviour of Map<String, V>.

System information:

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

Additional context N/A

mkarg avatar May 11 '23 06:05 mkarg