web-dev-qa-db-fra.com

Désérialiser dans une carte de hachage d'objets personnalisés avec jackson

J'ai la classe suivante:

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;

import Java.io.Serializable;
import Java.util.HashMap;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Theme implements Serializable {

    @JsonProperty
    private String themeName;

    @JsonProperty
    private boolean customized;

    @JsonProperty
    private HashMap<String, String> descriptor;

    //...getters and setters for the above properties
}

Quand j'exécute le code suivant:

    HashMap<String, Theme> test = new HashMap<String, Theme>();
    Theme t1 = new Theme();
    t1.setCustomized(false);
    t1.setThemeName("theme1");
    test.put("theme1", t1);

    Theme t2 = new Theme();
    t2.setCustomized(true);
    t2.setThemeName("theme2");
    t2.setDescriptor(new HashMap<String, String>());
    t2.getDescriptor().put("foo", "one");
    t2.getDescriptor().put("bar", "two");
    test.put("theme2", t2);
    String json = "";
    ObjectMapper mapper = objectMapperFactory.createObjectMapper();
    try {
        json = mapper.writeValueAsString(test);
    } catch (IOException e) {
        e.printStackTrace(); 
    }

La chaîne json produite ressemble à ceci:

{
  "theme2": {
    "themeName": "theme2",
    "customized": true,
    "descriptor": {
      "foo": "one",
       "bar": "two"
    }
  },
  "theme1": {
    "themeName": "theme1",
    "customized": false,
    "descriptor": null
  }
}

Mon problème est que la chaîne JSON ci-dessus se dés-sérizilise dans un 

HashMap<String, Theme> 

objet.

Mon code de désérialisation ressemble à ceci:

HashMap<String, Themes> themes =
        objectMapperFactory.createObjectMapper().readValue(json, HashMap.class);

Ce qui se désérialise en une carte de hachage avec les clés correctes, mais ne crée pas d'objets de thème pour les valeurs. Je ne sais pas quoi spécifier au lieu de "HashMap.class" dans la méthode readValue ().

Toute aide serait appréciée.

45
wbj

Vous devez créer un type de carte spécifique et l’indiquer dans le processus de désérialisation:

TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, Theme.class);
HashMap<String, Theme> map = mapper.readValue(json, mapType);
79
Michał Ziober

Vous pouvez utiliser la classe TypeReference qui effectue la transtypage de type pour mapper avec des types définis par l'utilisateur. Plus de documentation sur http://wiki.fasterxml.com/JacksonInFiveMinutes

ObjectMapper mapper = new ObjectMapper();
Map<String,Theme> result =
  mapper.readValue(src, new TypeReference<Map<String,Theme>>() {});
16
user2824471

Vous pouvez créer un POJO qui étend une carte.

Ceci est important pour traiter les cartes d'objets imbriquées.

{
  key1: { nestedKey1: { value: 'You did it!' } }
}

Ceci peut être désérialisé via:

class Parent extends HashMap<String, Child> {}

class Child extends HashMap<String, MyCoolPojo> {}

class MyCoolPojo { public String value; }

Parent parent = new ObjectMapper().readValue(json, Parent.class);
parent.get("key1").get("nestedKey1").value; // "You did it!"
0
00500005