Comment analyser une chaîne JSON en JsonNode à Jackson?

231

Cela devrait être si simple, mais je ne le trouve pas après avoir essayé pendant une heure #embarrasing.

J'ai besoin d'obtenir une chaîne JSON, par exemple {"k1":v1,"k2":v2}, analysée en tant que JsonNode.

JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = jp.readValueAsTree();

donne

java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree

fadmaa
la source
54
#embarrasing-- Nan. Si les choses simples ne sont pas simples, c'est le concepteur d'API qui a échoué, pas vous.
jameshfisher
@ Réponse de StaxMan dans le code: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Réponses:

371

Une légère variation sur la réponse de Richards mais readTreepeut prendre une chaîne afin que vous puissiez la simplifier pour:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
slashnick
la source
44
Pour tous ceux qui ont besoin ObjectNoded'une JsonNodeutilisation plutôt que d'une utilisationmapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst
5
@MatthewHerbst Dans 2.5.1, cela crée un nouveau nœud de texte avec la chaîne "{\" k1 \ ": \" v1 \ "}" plutôt que de l'analyser en JSON.
minexew
69

Vous devez utiliser un ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = mapper.readTree(jp);

Vous trouverez plus de documentation sur la création d'analyseurs syntaxiques ici .

Richard Fearn
la source
Est-il possible de prendre le JsonNode, de le modifier un peu, puis d'appeler mapper.readValue (nœud, classe); et sortir un cours?
portforwardpodcast
1
Oui. Il y a même un alias pour ça mapper.treeToValue(),. Mais readValue()ça marche aussi.
StaxMan
Le lien semble rompu
manuna
28

Une troisième variante:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
qerub
la source
Qu'est-ce qui vous a amené à passer dans JsonNode.class?
David
3
@David: Rien, donc la variante de slashnick est évidemment meilleure si vous voulez juste un JsonNode. Cependant, vous n'en voulez généralement pas JsonNode, alors je voulais montrer comment dire à Jackson quel genre de valeur vous voulez.
qerub
Pour moi, le passage JsonNodeétait apparemment nécessaire pour empêcher Jackson de le désérialiser comme autre chose - ce qui aurait échoué.
Cory Klein
5

La réponse de Richard est correcte. Alternativement, vous pouvez également créer un MappingJsonFactory(in org.codehaus.jackson.map) qui sait où trouver ObjectMapper. L'erreur que vous avez eue était parce que le régulier JsonFactory(du corepackage) n'a aucune dépendance à ObjectMapper(qui est dans le mapperpackage).

Mais généralement, vous n'utilisez ObjectMapperet ne vous inquiétez pas pour d' JsonParserautres composants de bas niveau - ils seront simplement nécessaires si vous souhaitez lier des parties de flux ou effectuer une manipulation de bas niveau.

StaxMan
la source
3
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
pdxleif
la source
0

Nouvelle approche de l'ancienne question. Une solution qui fonctionne à partir de Java 9+

ObjectNode agencyNode = new ObjectMapper().valueToTree(Map.of("key", "value"));

est plus lisible et plus facile à gérer pour les objets complexes. Ej

Map<String, Object> agencyMap = Map.of(
        "name", "Agencia Prueba",
        "phone1", "1198788373",
        "address", "Larrea 45 e/ calligaris y paris",
        "number", 267,
        "enable", true,
        "location", Map.of("id", 54),
        "responsible", Set.of(Map.of("id", 405)),
        "sellers", List.of(Map.of("id", 605))
);
ObjectNode agencyNode = new ObjectMapper().valueToTree(agencyMap);
Manuel Ortiz
la source