Java Language Désérialiser la collection JSON à la collection d'objets à l'aide de Jackson


Exemple

Supposons que vous ayez une classe de pojo Person

public class Person {
    public String name;

    public Person(String name) {
        this.name = name;
    }
}

Et vous voulez l'analyser dans un tableau JSON ou une carte d'objets Person. En raison de l'effacement du type, vous ne pouvez pas construire directement les classes de List<Person> et Map<String, Person> (et donc les utiliser pour désérialiser JSON) . Pour surmonter cette limitation, jackson propose deux approches: TypeFactory et TypeReference .

TypeFactory

L'approche adoptée ici consiste à utiliser une fabrique (et sa fonction d'utilitaire statique) pour créer votre type pour vous. Les paramètres pris en compte sont la collection que vous souhaitez utiliser (liste, ensemble, etc.) et la classe que vous souhaitez stocker dans cette collection.

TypeReference

L'approche par référence de type semble plus simple car elle vous permet d'économiser un peu de saisie et est plus propre. TypeReference accepte un paramètre de type, où vous passez le type souhaité List<Person> . Vous instanciez simplement cet objet TypeReference et l'utilisez comme conteneur de type.

Voyons maintenant comment désérialiser réellement votre JSON dans un objet Java. Si votre JSON est formaté en tant que tableau, vous pouvez le désérialiser en tant que liste. S'il existe une structure imbriquée plus complexe, vous souhaiterez désérialiser une carte. Nous examinerons des exemples des deux.

Désérialisation du tableau JSON

String jsonString = "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]"

Approche TypeFactory

CollectionType listType = 
    factory.constructCollectionType(List.class, Person.class);
List<Preson> list = mapper.readValue(jsonString, listType);

Approche TypeReference

TypeReference<Person> listType = new TypeReference<List<Person>>() {};
List<Person> list = mapper.readValue(jsonString, listType);

Désérialisation de la carte JSON

String jsonString = "{\"0\": {\"name\": \"Alice\"}, \"1\": {\"name\": \"Bob\"}}"

Approche TypeFactory

CollectionType mapType = 
    factory.constructMapLikeType(Map.class, String.class, Person.class);
List<Person> list = mapper.readValue(jsonString, mapType);

Approche TypeReference

TypeReference<Person> mapType = new TypeReference<Map<String, Person>>() {};
Map<String, Person> list = mapper.readValue(jsonString, mapType);

Détails

Déclaration d'importation utilisée:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;

Instances utilisées:

ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = mapper.getTypeFactory();

Remarque

Bien TypeReference approche TypeReference semble meilleure, elle présente plusieurs inconvénients:

  1. TypeReference doit être instancié à l'aide d'une classe anonyme
  2. Vous devez fournir une explication générique

Si vous ne le faites pas, vous risquez de perdre l'argument de type générique qui entraînera une défaillance de la désérialisation.