2017-09-19 5 views
1

Je sais comment déroulez un Object à Jackson, mais je ne peux pas trouver des exemples sur la façon de déroulez deux couches.Comment dire Jackson de faire un sous-élément l'élément de niveau supérieur

EndPoints API Sharepoint reviennent tout dans le format suivant:

{ 
    "d": { 
     "results": [ 
      { 
       /* lots objects with lots of properties 
        that are irrelevant to the question */ 
      } 
     ] 
    } 
} 

J'ai essayé ce qui suit et il ne fait pas l'objet results valeur de niveau supérieur.

this.om.readerFor(new TypeReference<List<User>>() {}) 
     .withRootName("d") 
     .readValue(response.parseAsString()); 

Comment puis-je dire Jackson pour commencer l'analyse syntaxique du results comme le haut niveau Arraysans avoir à créer une hiérarchie d'objets personnalisée et sans avoir à écrire un désérialiseur personnalisé. J'ai un objet personnalisé qui est annoté que cela va peupler, je veux TypeSafety donc Map<String,Object> n'est pas ce que je veux.

Répondre

2

Probablement pas la façon la plus efficace, mais peut essayer d'analyser l'objet comme un arbre d'abord, puis accédez au nœud dont vous avez besoin. Quelque chose comme ceci:

mapper.readerFor(new TypeReference<List<User>>() {}).readValue(mapper.readTree(json).get("d").get("results"))‌​; 

plus facile à lire:

mapper.convertValue(mapper.readTree(json).get("d").get("‌​results"), new TypeReference<List<User>>() {}); 
+0

Je suis venu avec une variation de cette solution indépendamment, je pense que c'est la meilleure façon d'obtenir ce que je veux. –

+1

Quant à * efficient *, il doit tout analyser une fois de toute façon, donc passer dans le 'JsonNode' pour commencer à convertir n'est pas moins efficace de manière significative. Cela fait juste ce qu'il fait normalement, mais en deux étapes explicites. Si ça devait être super efficace dans 'space' ou' time' je n'utiliserais pas 'Json' beaucoup moins' SharePoint' :-) –

+1

@JarrodRoberson ouais, je pense aussi que la performance n'est pas un gros problème ici. En fait, j'ai publié que je n'ai jamais testé la performance, en comptant toujours sur les autres mots des gens. Et après des tests de base: https://gist.github.com/varren/3b7468a1d7abadad4958fe6bd7d42d44#file-main-java-L153-L178 De point de temps, il ne semble pas si mauvais, peut être 2 fois plus lent pour les cas simples avec 1 champ dans l'utilisateur et probablement 30% plus lent pour le json complexe. Du point de l'espace, il est également presque deux fois moins efficace https://i.stack.imgur.com/bftGe.png puis des objets de wraper ou deserilizer personnalisé ou en ligne 'JsonParser' – varren

-1
@JsonRootName("d") 
class Data { 
    public Map<String, Object>[] results; 
} 

ObjectMapper mapper = new ObjectMapper(); 
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); 
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); 

Map<String, Object> results = new LinkedHashMap<>(); 
results.put("key1", "val1"); 
results.put("key2", "val2"); 

Data expected = new Data(); 
expected.results = new Map[1]; 
expected.results[0] = results; 

String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(expected); 
Data actual = mapper.readerFor(Data.class).readValue(json); 

chaîne JSON ressemble:

{ 
    "d" : { 
    "results" : [ { 
     "key1" : "val1", 
     "key2" : "val2" 
    } ] 
    } 
} 

post-scriptum Dans le cas où vous ne vous souciez pas de concrétion d'objet et Map<String, Object> est OK pour vous, alors vous pouvez utiliser comme ça.

Map<String, Object> results = (Map<String, Object>)((List<?>)mapper.readerFor(Map.class).<Map<String, Map<String, ?>>>readValues(json).next().get("d").get("results")).get(0); 
+1

* « sans avoir à créer une hiérarchie d'objets » * - Je ne veux pas avoir une classe spéciale pour cela comme je l'ai dit dans la question. –

+0

Si vous ne vous souciez pas d'objet concret et que Map est OK pour vous, alors je pense que vous pourriez faire comme: Map results = (Map ) ((Liste ) mapper.readerFor (Map.class). >> readValues ​​(json) .next(). get ("d"). get ("résultats")). get (0); –