118 votes

Désérialiser JSON en ArrayList<POJO> avec Jackson

J'ai une classe Java MyPojo que je souhaite désérialiser à partir de JSON. J'ai configuré une classe MixIn spéciale, MyPojoDeMixIn pour m'aider dans la désérialisation. MyPojo n'a que int y String des variables d'instance combinées avec des getters et setters appropriés. MyPojoDeMixIn ressemble à ceci :

public abstract class MyPojoDeMixIn {
  MyPojoDeMixIn(
      @JsonProperty("JsonName1") int prop1,
      @JsonProperty("JsonName2") int prop2,
      @JsonProperty("JsonName3") String prop3) {}
}

Dans mon client de test, je fais ce qui suit, mais bien sûr cela ne fonctionne pas au moment de la compilation parce qu'il y a une erreur de type JsonMappingException liée à une incompatibilité de type.

ObjectMapper m = new ObjectMapper();
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class);
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); }
catch (Exception e) { System.out.println(e) }

Je sais que je pourrais résoudre ce problème en créant un objet "Réponse" qui ne possède qu'un objet "Réponse". ArrayList<MyPojo> mais je devrais alors créer ces objets quelque peu inutiles pour chaque type que je veux renvoyer.

J'ai également consulté en ligne JacksonEnCinqMinutes mais j'ai eu beaucoup de mal à comprendre ce qui concerne les Map<A,B> et comment elle est liée à ma question. Si vous ne pouvez pas le deviner, je suis tout à fait novice en Java et je viens d'un milieu Obj-C. Ils mentionnent spécifiquement :

Outre la liaison avec les POJO et les types "simples", il existe une variante supplémentaire : la liaison à des conteneurs génériques (typés). Ce cas nécessite un traitement particulier en raison de l'utilisation de s (utilisé par Java pour implémenter les génériques d'une manière quelque peu rétrocompatible), qui vous empêche d'utiliser les types génériques. ), qui vous empêche d'utiliser quelque chose comme Collection.class (qui ne se compile pas).

Ainsi, si vous souhaitez lier des données à une carte, vous devrez utiliser :

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });

Comment puis-je désérialiser directement vers ArrayList ?

170voto

Perception Points 42290

Vous pouvez désérialiser directement vers une liste en utilisant la fonction TypeReference la couverture. Un exemple de méthode :

public static <T> T fromJSON(final TypeReference<T> type,
      final String jsonPacket) {
   T data = null;

   try {
      data = new ObjectMapper().readValue(jsonPacket, type);
   } catch (Exception e) {
      // Handle the problem
   }
   return data;
}

Il est utilisé de la sorte :

final String json = "";
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json);

TypeReference Javadoc

124voto

DevNG Points 753

Une autre méthode consiste à utiliser un tableau comme type, par exemple :

ObjectMapper objectMapper = new ObjectMapper();
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class);

De cette façon, vous évitez tous les problèmes liés à l'objet Type, et si vous avez vraiment besoin d'une liste, vous pouvez toujours convertir le tableau en une liste :

List<MyPojo> pojoList = Arrays.asList(pojos);

Cette version est beaucoup plus lisible.

Et pour en faire une véritable liste (qui peut être modifiée, voir les limites de Arrays.asList() ), il suffit de procéder comme suit :

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos));

50voto

Cette variante est plus simple et plus élégante.

//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.databind.type.CollectionType;
//import com.fasterxml.jackson.databind.type.TypeFactory;

//import java.util.List;

CollectionType typeReference =
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class);
List<Dto> resultDto = objectMapper.readValue(content, typeReference);

6voto

Jugal Panchal Points 148

Cela fonctionne pour moi.

@Test
public void cloneTest() {
    List<Part> parts = new ArrayList<Part>();
    Part part1 = new Part(1);
    parts.add(part1);
    Part part2 = new Part(2);
    parts.add(part2);
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonStr = objectMapper.writeValueAsString(parts);

        List<Part> cloneParts = objectMapper.readValue(jsonStr, new TypeReference<ArrayList<Part>>() {});
    } catch (Exception e) {
        //fail("failed.");
        e.printStackTrace();
    }

    //TODO: Assert: compare both list values.
}

4voto

rushidesai1 Points 31

J'ai le même problème. J'ai un json qui doit être converti en ArrayList.

Le compte se présente comme suit.

Account{
  Person p ;
  Related r ;

}

Person{
    String Name ;
    Address a ;
}

Toutes les classes ci-dessus ont été correctement annotées. J'ai essayé TypeReference>() {} mais cela ne fonctionne pas.

J'obtiens Arraylist, mais ArrayList contient un linkedHashMap qui contient d'autres hashmaps liés contenant les valeurs finales.

Mon code est le suivant :

public T unmarshal(String responseXML,String c)
{
    ObjectMapper mapper = new ObjectMapper();

    AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();

    mapper.getDeserializationConfig().withAnnotationIntrospector(introspector);

    mapper.getSerializationConfig().withAnnotationIntrospector(introspector);
    try
    {
      this.targetclass = (T) mapper.readValue(responseXML,  new TypeReference<ArrayList<T>>() {});
    }
    catch (JsonParseException e)
    {
      e.printStackTrace();
    }
    catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    return this.targetclass;
}

J'ai finalement résolu le problème. Je suis en mesure de convertir la liste dans Json String directement en ArrayList comme suit :

JsonMarshallerUnmarshaller<T>{

     T targetClass ;

     public ArrayList<T> unmarshal(String jsonString)
     {
        ObjectMapper mapper = new ObjectMapper();

        AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();

        mapper.getDeserializationConfig().withAnnotationIntrospector(introspector);

        mapper.getSerializationConfig().withAnnotationIntrospector(introspector);
        JavaType type = mapper.getTypeFactory().
                    constructCollectionType(ArrayList.class, targetclass.getClass()) ;
        try
        {
        Class c1 = this.targetclass.getClass() ;
        Class c2 = this.targetclass1.getClass() ;
            ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString,  type);
        return temp ;
        }
       catch (JsonParseException e)
       {
        e.printStackTrace();
       }
       catch (JsonMappingException e) {
           e.printStackTrace();
       } catch (IOException e) {
          e.printStackTrace();
       }

     return null ;
    }  

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X