Как разобрать строку JSON в JsonNode в Джексоне?

231

Это должно быть так просто, но я просто не могу найти его после попытки в течение часа # смущать.

Мне нужно получить строку 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

fadmaa
источник
54
#embarrasing-- Нет. Если простые вещи не так просты, значит, разработчик API потерпел неудачу, а не вы.
jameshfisher
@ Ответ StaxMan в коде: JsonFactory factory = new MappingJsonFactory ();
Хуан Рохас

Ответы:

371

Небольшое отклонение от ответа Ричардса, но readTreeможет взять строку, чтобы вы могли упростить ее до:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
slashnick
источник
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
Ссылка вроде битая
manuna
28

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

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
qerub
источник
Что на самом деле привело вас сюда в JsonNode.class?
Дэвид
3
@ Дэвид: Ничего, так что вариант Слэшника, очевидно, лучше, если вы просто хотите JsonNode. Тем не менее, вы обычно не хотите JsonNode, поэтому я хотел показать, как сказать Джексону, какую ценность вы хотите.
Qerub
Для меня прохождение, JsonNodeочевидно, было необходимо, чтобы помешать Джексону десериализовать его как что-то еще, что не состоялось бы.
Кори Кляйн
5

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

Но обычно вы просто используете ObjectMapperи не беспокоитесь о JsonParserдругих низкоуровневых компонентах - они просто необходимы, если вы хотите привязать данные к части потока или выполнить низкоуровневую обработку.

StaxMan
источник
3
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
pdxleif
источник
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);
Мануэль Ортис
источник