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.