Jackson - Unmarshall a Collection / Array

1. Panoramica

Questo tutorial mostrerà come deserializzare un array JSON in un array o una raccolta Java con Jackson 2 .

Se vuoi approfondire e imparare altre cose interessanti che puoi fare con Jackson 2, vai al tutorial principale di Jackson.

2. Unmarshall ad Array

Jackson può facilmente deserializzare in un array Java:

@Test public void givenJsonArray_whenDeserializingAsArray_thenCorrect() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); List listOfDtos = Lists.newArrayList( new MyDto("a", 1, true), new MyDto("bc", 3, false)); String jsonArray = mapper.writeValueAsString(listOfDtos); // [{"stringValue":"a","intValue":1,"booleanValue":true}, // {"stringValue":"bc","intValue":3,"booleanValue":false}] MyDto[] asArray = mapper.readValue(jsonArray, MyDto[].class); assertThat(asArray[0], instanceOf(MyDto.class)); }

3. Unmarshall alla raccolta

Leggere lo stesso array JSON in una raccolta Java è un po 'più difficile: per impostazione predefinita, Jackson non sarà in grado di ottenere le informazioni complete sul tipo generico e creerà invece una raccolta di istanze HashMap collegate :

@Test public void givenJsonArray_whenDeserializingAsListWithNoTypeInfo_thenNotCorrect() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); List listOfDtos = Lists.newArrayList( new MyDto("a", 1, true), new MyDto("bc", 3, false)); String jsonArray = mapper.writeValueAsString(listOfDtos); List asList = mapper.readValue(jsonArray, List.class); assertThat((Object) asList.get(0), instanceOf(LinkedHashMap.class)); }

Ci sono due modi per aiutare Jackson a capire le giuste informazioni sul tipo : possiamo usare il TypeReference fornito dalla libreria proprio per questo scopo:

@Test public void givenJsonArray_whenDeserializingAsListWithTypeReferenceHelp_thenCorrect() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); List listOfDtos = Lists.newArrayList( new MyDto("a", 1, true), new MyDto("bc", 3, false)); String jsonArray = mapper.writeValueAsString(listOfDtos); List asList = mapper.readValue( jsonArray, new TypeReference
    
     () { }); assertThat(asList.get(0), instanceOf(MyDto.class)); }
    

Oppure possiamo usare il metodo readValue sovraccarico che accetta un JavaType :

@Test publi void givenJsonArray_whenDeserializingAsListWithJavaTypeHelp_thenCorrect() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); List listOfDtos = Lists.newArrayList( new MyDto("a", 1, true), new MyDto("bc", 3, false)); String jsonArray = mapper.writeValueAsString(listOfDtos); CollectionType javaType = mapper.getTypeFactory() .constructCollectionType(List.class, MyDto.class); List asList = mapper.readValue(jsonArray, javaType); assertThat(asList.get(0), instanceOf(MyDto.class)); }

Un'ultima nota è che la classe MyDto deve avere il costruttore predefinito senza argomenti - in caso contrario, Jackson non sarà in grado di istanziarlo :

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.baeldung.jackson.ignore.MyDto]: can not instantiate from JSON object (need to add/enable type information?)

4. Conclusione

La mappatura di array JSON su raccolte java è una delle attività più comuni per cui viene utilizzato Jackson e queste soluzioni sono fondamentali per ottenere una mappatura corretta e indipendente dai tipi .

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata nel nostro progetto GitHub : questo è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.