Skip to content

Yasson 3.0.3 - Serialization of a Map fails if the key is of a type implemented as SupportedMapKey and using a csutom Serializer #663

Description

@jbaesner

Describe the bug
Define a custom Serializer for a LocalDate object like the following:

public static class LocalDateSerializer implements JsonbSerializer<LocalDate> {

    private static final DateTimeFormatter SHORT_FORMAT = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);

    @Override
    public void serialize(LocalDate obj, JsonGenerator generator, SerializationContext ctx) {
        generator.write(SHORT_FORMAT.format(obj));
    }
}

Note: This LocalDate is also included in the TypeSerializers.SUPPORTED_MAP_KEYS as default serialization implementation.

Now use a Pojo class that contains a Map field with LocalDate as the key:

public class TestObject {
  private Map<LocalDate, String> localDateKeyMap;
  ...
}

If you try to serialize it with current version 3.0.3 like the following:

        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
                .withSerializers(new LocalDateSerializer())
                .withDeserializers(new LocalDateDeserializer()));
        TestObject o = new TestObject();
        o.getLocalDateKeyMap().put(LocalDate.now(), "today");
        jsonb.toJson(o);

The following exception is thrown:

jakarta.json.bind.JsonbException: Unable to serialize property 'values' from test.MapObjectTest.MapObjectLocalDateString
        at org.eclipse.yasson.internal.serializer.ObjectSerializer.lambda$serialize$0(ObjectSerializer.java:43)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) 
        at org.eclipse.yasson.internal.serializer.ObjectSerializer.serialize(ObjectSerializer.java:38)
        at org.eclipse.yasson.internal.serializer.RecursionChecker.serialize(RecursionChecker.java:38)
        at org.eclipse.yasson.internal.serializer.KeyWriter.serialize(KeyWriter.java:41)
        at org.eclipse.yasson.internal.serializer.NullVisibilitySwitcher.serialize(NullVisibilitySwitcher.java:40)
        at org.eclipse.yasson.internal.serializer.NullSerializer.serialize(NullSerializer.java:67)
        at org.eclipse.yasson.internal.SerializationContextImpl.serializeObject(SerializationContextImpl.java:197)
        at org.eclipse.yasson.internal.SerializationContextImpl.marshall(SerializationContextImpl.java:133)                                  
        at org.eclipse.yasson.internal.SerializationContextImpl.marshall(SerializationContextImpl.java:159)
        at org.eclipse.yasson.internal.JsonBinding.toJson(JsonBinding.java:131)                                                                     
        at test.MapObjectTest.test1(MapObjectTest.java:102)                                                                                             
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) 
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)           
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)                                                                                                                                                                                                                     
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) 
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
        at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
        Suppressed: jakarta.json.stream.JsonGenerationException: Generating incomplete JSON
                at org.eclipse.parsson.JsonGeneratorImpl.close(JsonGeneratorImpl.java:519)
                at org.eclipse.yasson.internal.JsonBinding.toJson(JsonBinding.java:130)
                ... 29 more
Caused by: jakarta.json.stream.JsonGenerationException: Illegal method during JSON generation, not valid in current context IN_OBJECT
        at org.eclipse.parsson.JsonGeneratorImpl.checkContextForValue(JsonGeneratorImpl.java:405)
        at org.eclipse.parsson.JsonGeneratorImpl.write(JsonGeneratorImpl.java:357)
        at org.eclipse.yasson.internal.serializer.YassonGenerator.write(YassonGenerator.java:161)
        at test.MapObjectTest$LocalDateSerializer.serialize(MapObjectTest.java:36)
        at test.MapObjectTest$LocalDateSerializer.serialize(MapObjectTest.java:30)
        at org.eclipse.yasson.internal.serializer.UserDefinedSerializer.serialize(UserDefinedSerializer.java:35)
        at org.eclipse.yasson.internal.serializer.RecursionChecker.serialize(RecursionChecker.java:38)
        at org.eclipse.yasson.internal.serializer.KeyWriter.serialize(KeyWriter.java:41)
        at org.eclipse.yasson.internal.serializer.NullSerializer.serialize(NullSerializer.java:67)
        at org.eclipse.yasson.internal.serializer.MapSerializer$StringKeyMapSerializer.lambda$serialize$0(MapSerializer.java:108)
        at java.base/java.util.HashMap.forEach(HashMap.java:1337)
        at org.eclipse.yasson.internal.serializer.MapSerializer$StringKeyMapSerializer.serialize(MapSerializer.java:107)
        at org.eclipse.yasson.internal.serializer.KeyWriter.serialize(KeyWriter.java:41)
        at org.eclipse.yasson.internal.serializer.NullVisibilitySwitcher.serialize(NullVisibilitySwitcher.java:40)
        at org.eclipse.yasson.internal.serializer.NullSerializer.serialize(NullSerializer.java:67)
        at org.eclipse.yasson.internal.serializer.ValueGetterSerializer.serialize(ValueGetterSerializer.java:43)
        at org.eclipse.yasson.internal.serializer.ObjectSerializer.lambda$serialize$0(ObjectSerializer.java:41)
        ... 39 more

To Reproduce

unzip issue-map-local-date-key.zip
cd issue-map-local-date-key
mvn clean test

Expected behavior
The test should pass as with earlier yasson versions and the LocalDateSerializer should be used to serialize the LocalDate key into a String.

System information:

  • OS: any
  • Java Version: 11, 17
  • Yasson Version: 3.0.3

Additional context
The same was working in previous yasson versions.

Reproducer project: issue-map-local-date-key.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working right

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions