7

I have a POJO that has an inner map. I want this to deserialize into a HashMap from my JSON, but Jackson deserializes the inner map from the JSON into a LinkedHashMap. I can force it to use HashMap by changing the type of the Map from "Map" to "HashMap", but I want to know if there is a way to tell Jackson to deserialize into a specific implementation of Map?

Here is the JSON:

{
    "transforms": {
        "variable_name1": [{
            "min": 100,
            "max": 200,
            "value": 0.6
        }],
        "variable_name2": [{
            "min": 100,
            "max": 200,
            "value": 0.6
        }],
        "variable_name3": [{
            "min": 100,
            "max": 200,
            "value": 0.6
        }]
    }
}

And the Transforms class:

public class Transformer {
    Map<String, List<Transform>> transforms;

    public Transformer() {
        transforms = new HashMap<String, List<Transform>>();
    }

    public void setTransforms(Map<String, List<Transform>> transforms) {
        this.transforms = transforms;
    }
}

How I am using the ObjectMapper:

try(Reader reader = new InputStreamReader(TransformTester.class.getResourceAsStream("transforms.json"), "UTF-8")) {
            ObjectMapper objMapper = new ObjectMapper();
            Transformer tr = objMapper.readValue(reader, Transformer.class);
}
Seephor
  • 1,692
  • 3
  • 28
  • 50
  • 3
    Jackson is using `LinkedHashMap` to honor the order of the fields from the JSON. What is wrong with that? – Andreas Dec 23 '16 at 18:03
  • @Andreas Isn't there extra overhead with a LinkedHashMap? I don't care about the order. – Seephor Dec 23 '16 at 18:12
  • @SotiriosDelimanolis won't LinkedHashMap be slower and have more overhead because it has to maintain that order? I don't care about the order. – Seephor Dec 23 '16 at 18:16
  • 2
    You've benchmarked your app and determined that this is a problem? – Sotirios Delimanolis Dec 23 '16 at 18:36
  • @SotiriosDelimanolis no, just read the doc here: https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html. I imagine that when it scales up I will want a smaller footprint and slightly better performance though. – Seephor Dec 23 '16 at 19:45
  • 1
    @Seephor That would be [Premature Optimization](http://stackoverflow.com/q/385506/5221149), and you shouldn't waste time on it until you actually experience a problem. – Andreas Dec 23 '16 at 21:01
  • I benchmarked my app and this is truly a problem :C According to the profiler I have ~50% of time instantiating linkedhashmap nodes, which is 2 times more expensive than instantiating a hashmap nodes. – Netherwire May 22 '18 at 09:45

1 Answers1

3

If you want some other type, you can implement the Jackson converter and annotate your class with it.

public static class TransformConverter implements Converter<Map<String,List>,Map<String,List>>{

    @Override
    public Map<String,List> convert(Map<String,List> map) {
        return new HashMap<>(map);
    }

    @Override
    public JavaType getInputType(TypeFactory typeFactory) {
        return typeFactory.constructMapType(Map.class, String.class, List.class);
    }

    @Override
    public JavaType getOutputType(TypeFactory typeFactory) {
        return typeFactory.constructMapType(Map.class, String.class, List.class);
    }
}



public static class Transformer {
    @JsonDeserialize(converter = TransformConverter.class)
    Map<String, List<Transform>> transforms;
//rest of your class
}
Jan Cetkovsky
  • 776
  • 6
  • 4