Jak parsować ciąg JSON w JsonNode w Jacksonie?


231

Powinno to być takie proste, ale po prostu nie mogę go znaleźć po godzinnej próbie # zawstydzenia.

Muszę na przykład pobrać ciąg JSON {"k1":v1,"k2":v2}, przetworzony jako JsonNode.

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

daje

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


54
#embarrasing-- nie. Jeśli proste rzeczy nie są proste, to projektant API zawiódł, a nie ty.
jameshfisher

@ Odpowiedź StaxMan w kodzie: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Odpowiedzi:


371

Niewielka odmiana odpowiedzi Richardsa, ale readTreemożna pobrać ciąg znaków, aby uprościć:

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

44
Dla każdego, kto potrzebuje ObjectNoderaczej niż JsonNodeużyciamapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst

5
@MatthewHerbst W wersji 2.5.1 powoduje to utworzenie nowego węzła tekstowego z ciągiem „{\" k1 \ ": \" v1 \ "}" zamiast analizowania go jako JSON.
minexew

69

Musisz użyć 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);

Dalszą dokumentację dotyczącą tworzenia parserów można znaleźć tutaj .


Czy można pobrać JsonNode, zmodyfikować go nieco, a następnie wywołać mapper.readValue (węzeł, klasa); i wyjść z klasy?
portforwardpodcast

1
Tak. Jest nawet aliasem, że mapper.treeToValue(). Ale readValue()też działa.
StaxMan

Link wydaje się być zerwany
manuna

28

Trzeci wariant:

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

Co właściwie przekazało ci JsonNode.class?
David

3
@David: Nic, więc wariant slashnick jest oczywiście lepszy, jeśli tylko chcesz JsonNode. Jednak zazwyczaj nie chcesz JsonNode, więc chciałem pokazać, jak powiedzieć Jacksonowi, jakiej wartości chcesz.
qerub

Dla mnie przejście JsonNodebyło najwyraźniej konieczne, aby powstrzymać Jacksona przed deserializacją tego jako czegoś innego - co by się nie udało.
Cory Klein

5

Odpowiedź Richarda jest poprawna. Alternatywnie możesz również utworzyć MappingJsonFactory(w org.codehaus.jackson.map), który wie, gdzie znaleźć ObjectMapper. Wystąpił błąd, ponieważ zwykły JsonFactory(z corepakietu) nie jest zależny od ObjectMapper(który jest w mapperpakiecie).

Ale zwykle używasz ObjectMapperi nie martwisz się o JsonParserinne komponenty niskiego poziomu - będą one potrzebne tylko wtedy, gdy chcesz powiązać dane części strumienia lub wykonywać operacje na niskim poziomie.


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

0

Nowe podejście do starego pytania. Rozwiązanie, które działa z java 9+

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

jest bardziej czytelny i łatwy w utrzymaniu dla złożonych obiektów. 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);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.