Add EnumFeature.READ_ENUM_KEYS_USING_INDEX to work with existing "WRITE_ENUM_KEYS_USING_INDEX" · Issue #2536 · FasterXML/jackson-databind (original) (raw)

With #2129 and jackson 2.10.0 a new Feature WRITE_ENUM_KEYS_USING_INDEX was introduced.

So we now can write an enum used in a map as key as number/enum index.
(This is usefull as the other side is written in C and works indexed based, ...)
That works fine. See Example below.

Problem: the json generated by jackson this way cannot be deserialized.

This unbalanced situation - jackson cannot read his own json - was described in #1877

Seems jackson needs a feature like "READ_ENUM_KEYS_USING_INDEX" (suggestion regarding #2129 )

Sample Code explaining the situation:

package jackson_enum_as_key;

import com.fasterxml.jackson.databind.*;

import java.io.IOException;
import java.util.*;

public class Main {

    public enum Type {
        ANY,
        OTHER
    }

    public static class Container {
        private Type simpleType;
        private Map<Type, String> map;

        public Type getSimpleType() {
            return simpleType;
        }

        public void setSimpleType(Type simpleType) {
            this.simpleType= simpleType;
        }

        public Map<Type, String> getMap() {
            return map;
        }

        public void setMap(Map<Type, String> map) {
            this.map = map;
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, true);
        objectMapper.configure(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX, true);

        Map<Type, String> map = new HashMap<>();
        map.put(Type.OTHER, "hello world");
        Container container = new Container();
        container.setSimpleType(Type.ANY);
        container.setMap(map);

        String json = objectMapper.writeValueAsString(container);

        System.out.println(json);

        objectMapper.readValue(json, Container.class);
    }
}

Problem:

/opt/java/jdk1.8.0_151/bin/java jackson_enum_as_key.Main

{"simpleType":0,"map":{"1":"hello world"}}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize Map key of type `jackson_enum_as_key.Main$Type` from String "1": not a valid representation, problem: (com.fasterxml.jackson.databind.exc.InvalidFormatException) Cannot deserialize Map key of type `jackson_enum_as_key.Main$Type` from String "1": not one of the values accepted for Enum class: [OTHER, ANY]
 at [Source: (String)"{"simpleType":0,"map":{"1":"hello world"}}"; line: 1, column: 24] (through reference chain: jackson_enum_as_key.Main$Container["map"])
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.weirdKeyException(DeserializationContext.java:1653)
    at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdKey(DeserializationContext.java:886)
    at com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer.deserializeKey(StdKeyDeserializer.java:138)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBind(MapDeserializer.java:449)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:367)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
    at jackson_enum_as_key.Main.main(Main.java:51)

Process finished with exit code 1