2

I'd like to use Jackson to bind a Map<String, String> to a bean. The pitfall here is that the not all the fields are collections so it doesn't work.

I would need to tweak the ObjectMapper to only bind collections when the corresponding bean property is a collection.

public class MapperTest {

    public static class Person {
        public String fname;
        public Double age;
        public List<String> other;
    }

    public static void main(String[] args) {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String[]> props = new HashMap<>();
        props.put("fname", new String[] {"mridang"});
        props.put("age", new String[] {"1"});
        props.put("other", new String[] {"one", "two"});
        mapper.convertValue(props, Person.class);
    }
}

The above example doesn't work as Jackson expects all the fields to be collections.


I cannot change the Map structure as this is a legacy system I'm dealing with so I'm pretty much stuck with Map<String, String[]>

Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
  • You are providing collections so why would Jackson expect otherwise? – Antoniossss Jul 20 '18 at 07:12
  • A bit of a backstory here. I'm on a legacy web framework here that exposes all the URL query params as that hackish map. I'd like to migrate to a standardized ser-deser library and that seems to be my only way out. – Mridang Agarwalla Jul 20 '18 at 07:14
  • http://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/DeserializationFeature.html#ACCEPT_SINGLE_VALUE_AS_ARRAY Thats close, but you need the other way around ;) – Antoniossss Jul 20 '18 at 07:16
  • I cannot check that, but you can try `@JsonFormat(shape = JsonFormat.Shape.Array)` on non array fields. Maybeit will work on deserialization as well. – Antoniossss Jul 20 '18 at 07:21
  • @Antoniossss `DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY` won't word here. However `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS` does. See my [answer](https://stackoverflow.com/a/51438473/1426227). – cassiomolin Jul 20 '18 at 08:40
  • 1
    Great, I didnt know that exists and managed to find that only so I was on good track;) – Antoniossss Jul 20 '18 at 08:41

1 Answers1

4

You can use DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, as follows:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);

Map<String, String[]> props = new HashMap<>();
props.put("fname", new String[] {"mridang"});
props.put("age", new String[] {"1"});
props.put("other", new String[] {"one", "two"});

Person person = mapper.convertValue(props, Person.class);
cassiomolin
  • 124,154
  • 35
  • 280
  • 359