2010-09-06 17 views
179

Debería ser tan simple, pero no puedo encontrarlo después de intentar durante una hora #embarrasing.Cómo analizar una cadena JSON en JsonNode en Jackson?

Necesito obtener una cadena JSON, por ejemplo, {"k1":v1,"k2":v2}, analizada como JsonNode.

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

da

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

+38

'# embarrasing' - pues . Si las cosas simples no son simples, entonces el diseñador de API ha fallado, no usted. – jameshfisher

Respuesta

303

Una ligera variación en la respuesta, pero Richards readTree puede tomar una cadena por lo que puede simplificar a:

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

Para cualquier persona que necesite un 'ObjectNode' en lugar de un' JsonNode' use 'mapper.valueToTree (" {\ "k1 \": \ "v1 \"} ")' –

+5

@MatthewHerbst En 2.5.1, esto crea un nuevo Nodo de texto con la cadena "{\" k1 \ ": \" v1 \ "}" en lugar de analizarlo como JSON. – minexew

59

Es necesario utilizar un ObjectMapper como se muestra here: Respuesta

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

¿Es posible tomar el JsonNode, modificarlo un poco y luego llamar a mapper.readValue (node, class); y salir de una clase? – portforwardpodcast

+1

Sí. Incluso hay un alias para eso, 'mapper.treeToValue()'. Pero 'readValue()' también funciona. – StaxMan

5

de Richard es correcta. Alternativamente, también puede crear un MappingJsonFactory (en org.codehaus.jackson.map) que sepa dónde encontrar ObjectMapper. El error que recibió fue porque el JsonFactory normal (del paquete core) no tiene dependencia de ObjectMapper (que se encuentra en el paquete mapper).

Pero generalmente solo usa ObjectMapper y no se preocupe por JsonParser u otros componentes de bajo nivel: solo serán necesarios si desea vincular datos a partes de la transmisión o realizar un manejo de bajo nivel.

24

Una tercera variante:

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

¿Qué fue lo que pasó en JsonNode.class que te trajo aquí? – David

+3

@David: Nada, por lo que la variante de slashnick es obviamente mejor si solo quieres un 'JsonNode'. Sin embargo, normalmente no quiere un 'JsonNode', así que quería mostrarle a Jackson qué tipo de valor desea. – qerub

+0

Para mí, pasar 'JsonNode' era aparentemente necesario para evitar que Jackson lo deserializara como algo más, lo que habría fallado. –

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