2010-09-06 21 views
179

Dovrebbe essere così semplice, ma non riesco a trovarlo dopo aver provato per un'ora #embarrasing.Come analizzare una stringa JSON in JsonNode in Jackson?

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

+38

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

risposta

303

Una leggera variazione su Richards risposta, ma readTree può prendere una stringa in modo da poter semplificare a:

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

Per chi ha bisogno di un 'ObjectNode' piuttosto che un' 'usare JsonNode' mapper.valueToTree ("{\" k1 \ ": \" v1 \ "}")' –

+5

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

59

È necessario utilizzare un ObjectMapper come mostrato here: risposta

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); 
+0

E 'possibile prendere il JsonNode, modificarlo un po' e quindi chiamare mapper.readValue (node, class); e uscire da una classe? – portforwardpodcast

+1

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

5

di Richard è corretta. In alternativa è anche possibile creare un MappingJsonFactory (in org.codehaus.jackson.map) che sa dove trovare ObjectMapper. L'errore si è verificato perché il regolare JsonFactory (dal pacchetto core) non ha alcuna dipendenza da ObjectMapper (che si trova nel pacchetto mapper).

Ma in genere si utilizza solo ObjectMapper e non si preoccupa di JsonParser o di altri componenti di basso livello: saranno necessari solo se si desidera associare dati a parti di flusso o eseguire una gestione a basso livello.

24

una terza variante:

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

Cosa ti ha fatto passare di qui in JsonNode.class? – David

+3

@David: Niente, quindi la variante di slashnick è ovviamente migliore se vuoi solo un 'JsonNode'. Comunque, di solito non vuoi un 'JsonNode', quindi volevo mostrare come dire a Jackson che tipo di valore vuoi. – qerub

+0

Per me, passare 'JsonNode' era apparentemente necessario per impedire a Jackson di deserializzarlo come qualcos'altro - che avrebbe fallito. –

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