jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

Need a Feature like "READ_ENUM_KEYS_USING_INDEX"

Open mawifu opened this issue 5 years ago • 1 comments

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






mawifu avatar Nov 08 '19 12:11 mawifu

Support could be added via new EnumFeature mechanism, but implementation still needed.

I probably won't have time to tackle this but could help anyone who has time and interest.

cowtowncoder avatar Aug 03 '22 18:08 cowtowncoder

is there anyone working on this? I got some time off so I will make a PR in a day or two

JooHyukKim avatar Jan 29 '23 10:01 JooHyukKim

@JooHyukKim I don't think anyone is working on this, so go ahead! It could make it into 2.15; let me know if you need help with EnumFeature (you should be able to see how existing JsonNodeFeature is used, defined -- need to add the first enum value for EnumFeature but otherwise it should be easily accessible).

cowtowncoder avatar Jan 30 '23 01:01 cowtowncoder

@cowtowncoder thanks for your reply.

I actually did make a Pull Request on this yesterday.

I missed out EnumFeature on my PR, I thought READ_ENUM_KEYS_USING_INDEX config belonged to DeserializationFeature class? It'd be nice if you could help me out on understanding how EnumFeature relates here a little bit? 🥹

JooHyukKim avatar Jan 30 '23 01:01 JooHyukKim