Wie analysiere ich eine JSON-Zeichenfolge in JsonNode in Jackson?

230

Es sollte so einfach sein, aber ich kann es einfach nicht finden, nachdem ich es eine Stunde lang versucht habe #embarrasing.

Ich muss eine JSON-Zeichenfolge abrufen, die beispielsweise {"k1":v1,"k2":v2}als analysiert wird JsonNode.

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

gibt

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

Fadmaa
quelle
54
#embarrasing- Nein. Wenn einfache Dinge nicht einfach sind, ist der API-Designer gescheitert, nicht Sie.
Jameshfisher
@ StaxMans Antwort im Code: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Antworten:

371

Eine geringfügige Abweichung von Richards Antwort, readTreedie jedoch eine Zeichenfolge enthalten kann, um sie zu vereinfachen:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
Slashnick
quelle
44
Für alle, die ObjectNodeeher eine als eine JsonNodeVerwendung benötigenmapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst
5
@MatthewHerbst In 2.5.1 wird ein neuer Textknoten mit der Zeichenfolge "{" k1 ":" v1 "}" erstellt, anstatt ihn als JSON zu analysieren.
Minexew
69

Sie müssen Folgendes verwenden 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);

Weitere Dokumentationen zum Erstellen von Parsern finden Sie hier .

Richard Fearn
quelle
Ist es möglich, den JsonNode zu nehmen, ihn ein wenig zu ändern und dann mapper.readValue (Knoten, Klasse) aufzurufen? und eine Klasse raus?
Portforwardpodcast
1
Ja. Dafür gibt es sogar einen Alias mapper.treeToValue(). Funktioniert aber readValue()auch.
StaxMan
Die Verbindung scheint unterbrochen zu sein
Manuna
28

Eine dritte Variante:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
qerub
quelle
Was hat Sie das Passieren in JsonNode.class tatsächlich hierher gebracht?
David
3
@ David: Nichts, also ist Slashnicks Variante offensichtlich besser, wenn du nur eine willst JsonNode. Normalerweise willst du jedoch keine JsonNode, also wollte ich zeigen, wie man Jackson sagt, welchen Wert du haben willst.
Qerub
Für mich war das Bestehen JsonNodeanscheinend notwendig, um Jackson daran zu hindern, es als etwas anderes zu deserialisieren - was gescheitert wäre.
Cory Klein
5

Richards Antwort ist richtig. Alternativ können Sie auch ein MappingJsonFactory(in org.codehaus.jackson.map) erstellen, das weiß, wo es zu finden ist ObjectMapper. Der Fehler, den Sie erhalten haben, war, dass der reguläre JsonFactory(vom corePaket) keine Abhängigkeit von ObjectMapper(der im mapperPaket enthalten ist) hat.

Normalerweise verwenden Sie jedoch nur Komponenten auf niedriger Ebene ObjectMapperund machen sich keine Sorgen darüber JsonParser. Sie werden nur benötigt, wenn Sie Teile des Streams datenbinden oder auf niedriger Ebene verarbeiten möchten.

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