Como analisar uma string JSON no JsonNode em Jackson?


231

Deve ser tão simples, mas não consigo encontrá-lo depois de tentar por uma hora #embarrasing.

Eu preciso obter uma string JSON, por exemplo {"k1":v1,"k2":v2}, analisada como a 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-- Não. Se coisas simples não são simples, o designer da API falhou, não você.
Jameshfisher

@ Resposta do StaxMan no código: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Respostas:


371

Uma leve variação na resposta de Richards, mas readTreepode levar uma string, para que você possa simplificá-la para:

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

44
Para quem precisa de um ObjectNodeem vez de um JsonNodeusomapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst

5
@MatthewHerbst Na 2.5.1, isso cria um novo nó de texto com a string "{\" k1 \ ": \" v1 \ "}" em vez de analisá-lo como JSON.
Mxew 26/04

69

Você precisa usar um 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);

Mais documentação sobre a criação de analisadores pode ser encontrada aqui .


É possível pegar o JsonNode, modificá-lo um pouco e chamar o mapper.readValue (nó, classe); e sair de uma aula?
Portforwardpodcast

1
Sim. Existe até um apelido para isso mapper.treeToValue(). Mas readValue()também funciona.
23413 StaxMan

O link parece estar quebrado
manuna

28

Uma terceira variante:

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

O que a passagem no JsonNode.class realmente trouxe você aqui?
David

3
@ David: Nada, então a variante de slashnick é obviamente melhor se você só quer um JsonNode. No entanto, você geralmente não quer um JsonNode, então eu queria mostrar como dizer a Jackson que tipo de valor você deseja.
Qerub

Para mim, a passagem JsonNodeera aparentemente necessária para impedir que Jackson a desserializasse como outra coisa - o que teria falhado.
Cory Klein

5

A resposta de Richard está correta. Como alternativa, você também pode criar um MappingJsonFactory(in org.codehaus.jackson.map) que sabe onde encontrar ObjectMapper. O erro que você recebeu foi porque o regular JsonFactory(do corepacote) não tem dependência de ObjectMapper(que está no mapperpacote).

Mas geralmente você apenas usa ObjectMappere não se preocupa JsonParserou com outros componentes de baixo nível - eles serão necessários apenas se você desejar vincular partes do fluxo ou fazer manuseio de baixo nível.


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

0

Nova abordagem para a pergunta antiga. Uma solução que funciona a partir do java 9+

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

é mais legível e fácil de manter para objetos complexos. 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);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.