¿Cómo analizar una cadena JSON en JsonNode en Jackson?


231

Debería ser tan simple, pero no puedo encontrarlo después de haberlo intentado durante una hora.

Necesito obtener una cadena JSON, por ejemplo {"k1":v1,"k2":v2}, analizada como a 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


54
#embarrasing- no Si las cosas simples no son simples, entonces el diseñador de la API ha fallado, no tú.
jameshfisher

Respuesta de @ StaxMan en el código: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Respuestas:


371

Una ligera variación en la respuesta de Richards, pero readTreepuede tomar una cadena para que pueda simplificarla a:

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

44
Para cualquiera que necesite un uso en ObjectNodelugar de un JsonNodeusomapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst

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

69

Necesitas usar 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);

Puede encontrar más documentación sobre la creación de analizadores aquí .


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

1
Si. Incluso hay un alias para que, mapper.treeToValue(). Pero readValue()también funciona.
StaxMan

El enlace parece estar roto
manuna

28

Una tercera variante:

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

¿Qué te hizo pasar aquí en JsonNode.class?
David

3
@David: Nada, así que la variante de Slashnick es obviamente mejor si solo quieres una JsonNode. Sin embargo, por lo general no quieres un JsonNode, así que quería mostrarte cómo decirle a Jackson qué tipo de valor quieres.
qerub

Para mí, JsonNodeaparentemente era necesario pasar para evitar que Jackson lo deserializara como algo más, lo que habría fallado.
Cory Klein

5

La respuesta de Richard es correcta. Alternativamente, también puede crear un MappingJsonFactory(in org.codehaus.jackson.map) que sepa dónde encontrar ObjectMapper. El error que obtuvo fue porque el regular JsonFactory(del corepaquete) no tiene dependencia ObjectMapper(que está en el mapperpaquete).

Pero generalmente solo usa ObjectMappery no se preocupa por JsonParserotros componentes de bajo nivel; solo serán necesarios si desea unir partes de datos de la transmisión o hacer un manejo de bajo nivel.


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

0

Nuevo enfoque a la vieja pregunta. Una solución que funciona desde java 9+

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

es más legible y mantenible para objetos complejos. 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);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.