Skip to content

unable to deserialize map with non-string key  #532

@nikoncode

Description

@nikoncode

Guys,

Entry with custom typed key is missing in the result during map deserialization.
Possible reason that custom typed fields are deserialized as JsonToken.VALUE_EMBEDDED_OBJECT which is not acceptable for MapDeserializer since it requires field.

As a result serialization/deserialization loop is broken.

Snipped below reproduces the problem (but simplified):

package qwe;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.msgpack.jackson.dataformat.*;

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

import static java.util.Collections.singletonMap;

public class Library {
    private static final byte UUID_TYPE_CODE = 1;

    public static void main(String[] args) throws IOException {
        ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers();
        extTypeCustomDesers.addCustomDeser(UUID_TYPE_CODE, UUIDSerializer::fromBytes);

        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers));

        SimpleModule simpleModule = new SimpleModule();

        simpleModule.addSerializer(new UUIDSerializer(UUID_TYPE_CODE));
        simpleModule.addKeySerializer(Object.class, new MessagePackKeySerializer());
        objectMapper.registerModule(simpleModule);


        System.out.println(objectMapper.readValue(
                objectMapper.writeValueAsBytes(singletonMap(UUID.randomUUID(), UUID.randomUUID())), new TypeReference<Map<UUID, UUID>>() {
                }));
    }

    public static class UUIDSerializer extends StdSerializer<UUID> {

        private final byte code;

        public UUIDSerializer(byte code) {
            super(UUID.class);
            this.code = code;
        }

        public void serialize(UUID value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
            if (jsonGenerator instanceof MessagePackGenerator) {
                MessagePackGenerator messagePackGenerator = (MessagePackGenerator) jsonGenerator;
                messagePackGenerator.writeExtensionType(new MessagePackExtensionType(code, toBytes(value)));
            } else {
                throw new RuntimeException("Something went wrong with the serialization");
            }
        }

        @SuppressWarnings("WeakerAccess")
        public static byte[] toBytes(UUID value) {
            //original code removed
            return value.toString().getBytes();
        }

        public static UUID fromBytes(byte[] value) {
            //original code removed
            return UUID.fromString(new String(value));
        }

    }
}

Does it possible to somehow bypass this restriction and use custom types as a key in maps?

P.S.: dependency versions

    implementation 'com.fasterxml.jackson.core:jackson-core:2.11.2'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.2'
    implementation 'org.msgpack:jackson-dataformat-msgpack:0.8.21'

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions