2016-09-25 1 views
2

J'ai un fichier JSON (que je ne contrôle pas) qui ressemble à ceci:Jackson JsonTypeInfo pour le contenu de HashMap <String, Object>

{ 
    "some-identifier": { 
    "@class": "some-prefix.ClassA", 
    "<classA-property1>": "value1", 
    "<classA-property2>": "value2", 
    }, 
    "some-other-identifier": { 
    "@class": "some-other-prefix.ClassB", 
    "<classB-property1>": <... possibly nested objects ...> 
    }, 
    <...> 
} 

(Les CLASSA-propriétés et ClassB-propriétés sont les Je souhaite désérialiser cela dans un HashMap (mappant chaque identifiant à l'objet réel) et je veux utiliser un TypeIdResolver personnalisé pour déterminer la classe à instancier. (que je peux déterminer à partir du préfixe et du nom de classe). Les objets eux-mêmes doivent ensuite être désérialisés en utilisant le désérialiseur par défaut. Après beaucoup de recherches, je ne pouvais pas faire ce travail. J'ai besoin d'un moyen d'annoter le HashMap afin de définir JsonTypeInfo et JsonTypeIdResolver pour son contenu. Tous les exemples que j'ai vus jusqu'à présent ont ces annotations sur un type de base dont toutes les sous-classes s'étendent. Cependant, dans mon cas, il n'y a pas de classe parente commune pour les classes contenues dans le JSON (sauf Object bien sûr). Je pensais à l'annotation d'Object elle-même avec un mixin, mais même dans ce cas, la désérialisation par défaut pour les objets contenus serait rompue car elle attendrait une propriété @class sur tous les objets enfants.

Existe-t-il une solution pour ce scénario?

Répondre

0

Je pense que vous pouvez accomplir cela en permettant à l'information de type par défaut pour le mappeur d'objets comme celui-ci:

new ObjectMapper().enableDefaultTyping(
     ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, 
     JsonTypeInfo.As.PROPERTY); 

Voici un exemple complet:

public class JacksonDefaultTypeInfo { 
    static class Bean1 { 
     public String value; 

     Bean1() {} 

     public Bean1(final String value) { 
      this.value = value; 
     } 

     @Override 
     public String toString() { 
      return "Bean1{" + 
        "value='" + value + '\'' + 
        '}'; 
     } 
    } 

    static class Bean2 { 
     public int number; 

     Bean2() {} 

     Bean2(final int number) { 
      this.number = number; 
     } 


    } 

    public static void main(String[] args) throws IOException { 
     final Map<String, Object> map = new HashMap<>(); 
     map.put("bean1", new Bean1("string")); 
     map.put("bean2", new Bean2(123)); 

     final ObjectMapper objectMapper = new ObjectMapper() 
       .enableDefaultTyping(
         ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, 
         JsonTypeInfo.As.PROPERTY); 
     final String json = objectMapper 
       .writerWithDefaultPrettyPrinter() 
       .writeValueAsString(map); 

     System.out.println(json); 
     final Map<String, Object> result = objectMapper.readValue(
       json, 
       new TypeReference<Map<String, Object>>() {}); 
     System.out.println(result); 
    } 
} 

Sortie:

{ 
    "bean1" : { 
    "@class" : "stackoverflow.JacksonDefaultTypeInfo$Bean1", 
    "value" : "string" 
    }, 
    "bean2" : { 
    "@class" : "stackoverflow.JacksonDefaultTypeInfo$Bean2", 
    "number" : 123 
    } 
} 
{bean1=Bean1{value='string'}, bean2=Bean2{number=123}}