Як проаналізувати рядок JSON в JsonNode в Джексоні?


231

Це має бути таким простим, але я просто не можу його знайти після спроби протягом години #embarrasing.

Мені потрібно отримати рядок JSON, наприклад {"k1":v1,"k2":v2}, проаналізований як JsonNode.

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

дає

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


54
#embarrasing- ніпе. Якщо прості речі не є простими, то дизайнер API вийшов з ладу, не ви.
jameshfisher

@ Відповідь StaxMan у коді: JsonFactory factory = new MappingJsonFactory ();
Хуан Рохас

Відповіді:


371

Незначна зміна відповіді Річардса, але readTreeможе взяти рядок, щоб ви могли спростити її до:

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

44
Для всіх, хто потребує ObjectNodeскоріше JsonNodeвикористанняmapper.valueToTree("{\"k1\":\"v1\"}")
Метью Гербст

5
@MatthewHerbst У 2.5.1 це створює новий текстовий вузол із рядком "{\" k1 \ ": \" v1 \ "}", а не аналізує його як JSON.
minexew

69

Вам потрібно використовувати 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);

Подальшу документацію про створення парсерів можна знайти тут .


Чи можливо взяти JsonNode, трохи змінити його, а потім викликати mapper.readValue (вузол, клас); і вийти з класу?
portforwardpodcast

1
Так. Там навіть псевдонім для цього mapper.treeToValue(). Але readValue()також працює.
StaxMan

Здається, посилання розірвана
мануна

28

Третій варіант:

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

Що насправді переїхав у JsonNode.class вас сюди?
Девід

3
@David: Нічого, тому варіант Slashnick, очевидно, краще, якщо ви просто хочете JsonNode. Однак ти зазвичай не хочеш JsonNode, тому я хотів показати, як сказати Джексону, яку цінність ти хочеш.
qerub

Для мене проходження, JsonNodeочевидно, було необхідне для того, щоб не допустити Джексона деаріалізувати це як щось інше - що могло б провалитися.
Cory Klein

5

Відповідь Річарда правильна. Ви також можете створити MappingJsonFactoryorg.codehaus.jackson.map), який знає, де його знайти ObjectMapper. Ви отримали помилку, оскільки звичайний JsonFactory(від coreпакета) не залежить від ObjectMapper(який є в mapperпакеті).

Але зазвичай ви просто використовуєте ObjectMapperі не турбуєтесь про JsonParserінші компоненти низького рівня - вони просто знадобляться, якщо ви хочете пов’язати дані потоку частин потоку або зробити обробку низького рівня.


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

0

Новий підхід до старого питання. Рішення, яке працює від Java 9+

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

є більш читабельним і доступним для обслуговування складних об'єктів. 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.