Come analizzare una stringa JSON in JsonNode a Jackson?


231

Dovrebbe essere così semplice, ma non riesco a trovarlo dopo aver provato per un'ora a imbarazzare.

Ho bisogno di ottenere una stringa JSON, ad esempio {"k1":v1,"k2":v2}, analizzata come JsonNode.

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

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


54
#embarrasing-- no. Se le cose semplici non sono semplici, allora il progettista API ha fallito, non tu.
jameshfisher,

@ Risposta di StaxMan nel codice: fabbrica JsonFactory = new MappingJsonFactory ();
Juan Rojas,

Risposte:


371

Una leggera variazione sulla risposta di Richards ma readTreepuò prendere una stringa in modo da poterla semplificare per:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");

44
Per chiunque abbia bisogno ObjectNodedi un JsonNodeuso piuttosto che di un usomapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst,

5
@MatthewHerbst In 2.5.1, questo crea un nuovo nodo di testo con la stringa "{\" k1 \ ": \" v1 \ "}" anziché analizzarlo come JSON.
minexew

69

Devi usare 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);

Ulteriore documentazione sulla creazione di parser è disponibile qui .


È possibile prendere JsonNode, modificarlo un po 'e quindi chiamare mapper.readValue (nodo, classe); e uscire da una lezione?
portforwardpodcast,

1
Sì. C'è anche un alias per questo, mapper.treeToValue(). Ma readValue()funziona anche.
StaxMan

Il collegamento sembra interrotto
manuna

28

Una terza variante:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);

Cosa ti ha portato a passare in JsonNode.class?
David,

3
@ David: Niente, quindi la variante di Slashnick è ovviamente migliore se vuoi solo un JsonNode. Tuttavia, di solito non vuoi un JsonNode, quindi volevo mostrare come dire a Jackson che tipo di valore desideri.
qerub,

Per me, passare JsonNodeapparentemente era necessario per impedire a Jackson di deserializzarlo come qualcos'altro - il che sarebbe fallito.
Cory Klein,

5

La risposta di Richard è corretta. In alternativa puoi anche creare un MappingJsonFactory(in org.codehaus.jackson.map) che sa dove trovare ObjectMapper. L'errore che hai ricevuto è stato perché il normale JsonFactory(dal corepacchetto) non ha alcuna dipendenza da ObjectMapper(che è nel mapperpacchetto).

Ma di solito usi ObjectMappere non ti preoccupare JsonParsero di altri componenti di basso livello: saranno necessari solo se desideri collegare parti del flusso di dati o eseguire una gestione di basso livello.


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

0

Nuovo approccio alla vecchia domanda. Una soluzione che funziona da Java 9+

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

è più leggibile e gestibile per oggetti complessi. 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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.