267

It should be so simple, but I just cannot find it after being trying for an hour.

I need to get a JSON string, for example, {"k1":v1,"k2":v2}, parsed as a JsonNode.

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

gives

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

FanoFN
  • 6,815
  • 2
  • 13
  • 33
fadmaa
  • 3,067
  • 3
  • 18
  • 14

6 Answers6

424

A slight variation on Richards answer but readTree can take a string so you can simplify it to:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
John Gietzen
  • 48,783
  • 32
  • 145
  • 190
slashnick
  • 26,167
  • 10
  • 55
  • 67
  • 48
    For anyone who needs an `ObjectNode` rather than a `JsonNode` use `mapper.valueToTree("{\"k1\":\"v1\"}")` – Matthew Herbst Feb 18 '15 at 22:14
  • 8
    @MatthewHerbst In 2.5.1, this creates a new text node with the string "{\"k1\":\"v1\"}" rather than parsing it as JSON. – minexew Apr 26 '16 at 15:42
73

You need to use an 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);

Further documentation about creating parsers can be found here.

Richard Fearn
  • 25,073
  • 7
  • 56
  • 55
  • Is it possible to take the JsonNode, modify it a bit, and then call mapper.readValue(node, class); and get out a class? – benathon Jul 26 '12 at 03:56
  • 1
    Yes. There's even an alias for that, `mapper.treeToValue()`. But `readValue()` also works. – StaxMan Jul 04 '13 at 18:19
32

A third variant:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
qerub
  • 1,526
  • 16
  • 11
  • What did passing in JsonNode.class actually get you here? – David Oct 24 '13 at 18:10
  • 3
    @David: Nothing, so slashnick's variant is obviously better if you just want a `JsonNode`. However, you usually don't want a `JsonNode`, so I wanted to show how to tell Jackson what kind of value of you want. – qerub Nov 16 '13 at 18:33
  • For me, passing `JsonNode` was apparently necessary to prevent Jackson from deserializing it as something else - which would have failed. – Cory Klein Feb 26 '15 at 03:44
5
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
pdxleif
  • 1,750
  • 16
  • 15
5

Richard's answer is correct. Alternatively you can also create a MappingJsonFactory (in org.codehaus.jackson.map) which knows where to find ObjectMapper. The error you got was because the regular JsonFactory (from core package) has no dependency to ObjectMapper (which is in the mapper package).

But usually you just use ObjectMapper and do not worry about JsonParser or other low level components -- they will just be needed if you want to data-bind parts of stream, or do low-level handling.

JJD
  • 50,076
  • 60
  • 203
  • 339
StaxMan
  • 113,358
  • 34
  • 211
  • 239
3

New approach to old question. A solution that works from java 9+

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

is more readable and maintainable for complex objects. 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
  • 593
  • 5
  • 11