Ich versuche, unformatiertes JSON in ein Java-Objekt aufzunehmen, wenn das Objekt mit Jackson (de) serialisiert wird. Um diese Funktionalität zu testen, habe ich folgenden Test geschrieben:
public static class Pojo {
public String foo;
@JsonRawValue
public String bar;
}
@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {
String foo = "one";
String bar = "{\"A\":false}";
Pojo pojo = new Pojo();
pojo.foo = foo;
pojo.bar = bar;
String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";
ObjectMapper objectMapper = new ObjectMapper();
String output = objectMapper.writeValueAsString(pojo);
System.out.println(output);
assertEquals(json, output);
Pojo deserialized = objectMapper.readValue(output, Pojo.class);
assertEquals(foo, deserialized.foo);
assertEquals(bar, deserialized.bar);
}
Der Code gibt die folgende Zeile aus:
{"foo":"one","bar":{"A":false}}
Mit dem JSON möchte ich genau, dass die Dinge aussehen. Leider schlägt der Code mit einer Ausnahme fehl, wenn versucht wird, den JSON wieder in das Objekt einzulesen. Hier ist die Ausnahme:
org.codehaus.jackson.map.JsonMappingException: Instanz von java.lang.String kann nicht aus dem START_OBJECT-Token unter [Quelle: java.io.StringReader@d70d7a; Zeile: 1, Spalte: 13] (durch Referenzkette: com.tnal.prism.cobalt.gather.testing.Pojo ["bar"])
Warum funktioniert Jackson in einer Richtung gut, scheitert aber in der anderen Richtung? Es scheint, dass es in der Lage sein sollte, seine eigene Ausgabe wieder als Eingabe zu verwenden. Ich weiß, was ich versuche, ist unorthodox (der allgemeine Rat ist, ein inneres Objekt zu erstellen, für bar
das eine Eigenschaft namens benannt ist A
), aber ich möchte überhaupt nicht mit diesem JSON interagieren. Mein Code fungiert als Durchgang für diesen Code. Ich möchte diesen JSON aufnehmen und erneut senden, ohne etwas zu berühren, da ich bei Änderungen des JSON nicht möchte, dass mein Code geändert werden muss.
Danke für den Hinweis.
BEARBEITEN: Pojo wurde zu einer statischen Klasse gemacht, die einen anderen Fehler verursachte.
quelle
Nach der Antwort von @StaxMan habe ich Folgendes wie einen Zauber gemacht:
Und um der Ausgangsfrage treu zu bleiben, hier der Arbeitstest:
quelle
getJson()
zurückkommtString
. Wenn es nurJsonNode
das zurückgibt, was über den Setter eingestellt wurde, wird es wie gewünscht serialisiert, nein?node.asText()
gibt den leeren Wert gegenüber zurücktoString()
.Ich konnte dies mit einem benutzerdefinierten Deserializer tun (von hier aus ausschneiden und einfügen )
quelle
@JsonRawValue
@JsonSetter kann helfen. Siehe mein Beispiel ('Daten' sollen nicht analysiertes JSON enthalten):
quelle
Zusätzlich zu Roy Trueloves großartiger Antwort können Sie den benutzerdefinierten Deserialisator wie folgt injizieren
@JsonRawValue
:quelle
Dies ist ein Problem mit Ihren inneren Klassen. Die
Pojo
Klasse ist eine nicht statische innere Klasse Ihrer Testklasse, und Jackson kann diese Klasse nicht instanziieren. So kann es serialisieren, aber nicht deserialisieren.Definieren Sie Ihre Klasse folgendermaßen neu:
Beachten Sie die Hinzufügung von
static
quelle
Diese einfache Lösung hat bei mir funktioniert:
So konnte ich den Rohwert von JSON in der Variablen rawJsonValue speichern, und dann war es kein Problem, ihn (als Objekt) mit anderen Feldern zurück an JSON zu deserialisieren und über meinen REST zu senden. Die Verwendung von @JsonRawValue hat mir nicht geholfen, da gespeichertes JSON als String deserialisiert wurde, nicht als Objekt, und das war nicht das, was ich wollte.
quelle
Dies funktioniert sogar in einer JPA-Entität:
Im Idealfall stammen der ObjectMapper und sogar JsonFactory aus dem Kontext und sind so konfiguriert, dass Ihr JSON korrekt behandelt wird (Standard- oder Nicht-Standardwerte wie z. B. 'Infinity'-Floats).
quelle
JsonNode.toString()
Dokumentation istMethod that will produce developer-readable representation of the node; which may <b>or may not</b> be as valid JSON.
dies also eine sehr riskante Implementierung.JsonNode.asText()
intern und gibt Infinity- und andere nicht standardmäßige JSON-Werte aus.Hier ist ein voll funktionsfähiges Beispiel für die Verwendung von Jackson-Modulen, um in
@JsonRawValue
beide Richtungen zu arbeiten (Serialisierung und Deserialisierung):Anschließend können Sie das Modul nach dem Erstellen des registrieren
ObjectMapper
:quelle
org.codehaus.jackson
Paket, ohne es zu merken. Stellen Sie sicher, dass alle Ihre Importe von kommencom.fasterxml.jackson
.Ich hatte genau das gleiche Problem. Ich habe die Lösung in diesem Beitrag gefunden: Analysieren Sie den JSON-Baum mithilfe von Jackson oder seinen Alternativen in eine einfache Klasse
Schauen Sie sich die letzte Antwort an. Durch Definieren eines benutzerdefinierten Setters für die Eigenschaft, die einen JsonNode als Parameter verwendet und die toString-Methode für den jsonNode aufruft, um die String-Eigenschaft festzulegen, funktioniert alles.
quelle
Die Verwendung eines Objekts funktioniert in beide Richtungen einwandfrei ... Bei dieser Methode wird der Rohwert in zwei Schritten deserialisiert.
RawHello.java
RawJsonValue.java
quelle
Ich hatte ein ähnliches Problem, verwendete aber eine Liste mit vielen JSON-itens (
List<String>
).Ich habe die Serialisierung mithilfe der
@JsonRawValue
Anmerkung verwaltet. Für die Deserialisierung musste ich jedoch einen benutzerdefinierten Deserializer erstellen, der auf Roys Vorschlag basiert.Unten sehen Sie meinen Deserializer "List".
quelle