Probleme beim Deserialisieren Ausnahme/throwable mit Jackson in Java
Ich bin vor Probleme bei der Deserialisierung Exception
und Throwable
Instanzen, die mit Jackson (version 2.2.1). Betrachten Sie den folgenden Codeausschnitt:
public static void main(String[] args) throws IOException
{
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
try {
Integer.parseInt("String");
}
catch (NumberFormatException e) {
RuntimeException runtimeException = new RuntimeException(e);
String serializedException = objectMapper.writeValueAsString(runtimeException);
System.out.println(serializedException);
Throwable throwable = objectMapper.readValue(serializedException, Throwable.class);
throwable.printStackTrace();
}
}
Die Ausgabe von System.out.println
im catch
block:
{
"@class" : "java.lang.RuntimeException",
"detailMessage" : "java.lang.NumberFormatException: For input string: \"String\"",
"cause" : {
"@class" : "java.lang.NumberFormatException",
"detailMessage" : "For input string: \"String\"",
"cause" : null,
"stackTrace" : [ {
"declaringClass" : "java.lang.NumberFormatException",
"methodName" : "forInputString",
"fileName" : "NumberFormatException.java",
"lineNumber" : 65
}, {
"declaringClass" : "java.lang.Integer",
"methodName" : "parseInt",
"fileName" : "Integer.java",
"lineNumber" : 492
}, {
"declaringClass" : "java.lang.Integer",
"methodName" : "parseInt",
"fileName" : "Integer.java",
"lineNumber" : 527
}, {
"declaringClass" : "test.jackson.JacksonTest",
"methodName" : "main",
"fileName" : "JacksonTest.java",
"lineNumber" : 26
} ],
"suppressedExceptions" : [ "java.util.ArrayList", [ ] ]
},
"stackTrace" : [ {
"declaringClass" : "test.jackson.JacksonTest",
"methodName" : "main",
"fileName" : "JacksonTest.java",
"lineNumber" : 29
} ],
"suppressedExceptions" : [ "java.util.ArrayList", [ ] ]
}
scheint in Ordnung. Aber wenn ich Versuch zu Deserialisieren diese mit objectMapper.readValue()
bekomme ich folgende exception:
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "declaringClass" (class java.lang.StackTraceElement), not marked as ignorable
at [Source: java.io.StringReader@3c5ebd39; line: 9, column: 27] (through reference chain: java.lang.StackTraceElement["declaringClass"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708)
at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StackTraceElementDeserializer.deserialize(JdkDeserializers.java:414)
at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StackTraceElementDeserializer.deserialize(JdkDeserializers.java:380)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:151)
...
Habe ich dann versucht, mit mix-in Anmerkungen, zu ignorieren declaringClass
im java.lang.StackTraceElement
, aber jetzt ist die deserialisiert Exception
nicht enthalten, die die Deklaration der Klasse in seinem stack trace:
java.lang.RuntimeException: java.lang.NumberFormatException: For input string: "String"
at .main(JacksonTest.java:33)
Caused by: java.lang.NumberFormatException: For input string: "String"
at .forInputString(NumberFormatException.java:65)
at .parseInt(Integer.java:492)
at .parseInt(Integer.java:527)
at .main(JacksonTest.java:30)
Bin ich etwas fehlt? Jede Hilfe wird sehr geschätzt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Scheint es eine Jackson JIRA-Eintrag für diese hier. Jackson scheint nicht in der Lage sein zu handhaben, die
declaringClass
imjava.lang.StackTraceElement
, da die getter entsprechend dieses Feld heißtgetClassName()
.Ich das Problem behoben, indem Sie mithilfe eines benutzerdefinierten wrapper
StackTraceElement
wie vorgeschlagen in den JIRA-Eintrag erwähnt. Die benutzerdefinierten wrapper (CustomStackTraceElement
) die FelderdeclaringClass
,methodName
,fileName
, undlineNumber
und die entsprechenden Getter und setter drin. Ich veränderte diecatch
block (in der Frage genannten), werden wie folgt:Den
StackTraceElement[]
umgewandelt wirdList<CustomStackTraceElement>
durch die folgende Methode während der Serialisierung:... und die umgekehrte Umwandlung erfolgt während der Deserialisierung:
Nun, nach der Deserialisierung, die
Throwable
Objekt hat die erwartete stack-trace in es.Fügen Sie diese:
Und machen aus der Ausnahme deserialisiert die gleiche Weise, wie für das erste mal:
Ich verwendete den folgenden code:
Hinzugefügt, diese Gläser: jackson-annotations-2.2.0.jar, jackson-core-2.2.0.jar und jackson-databind-2.2.0.jar.
Nach der Ausführung der folgenden abgedruckt ist:
DeserializationFeature
, aber ich bekomme die gleiche Ausgabe wie das mit mix-in-Annotationen (d.h., es gibt keine Deklaration der Klasse in der die deserialisierte Ausgabe). Ich brauche die kompletteException
/Throwable
Informationen nach ist es deserialisiert -- es sieht komisch und unvollständig, sonst.t understand, why are you trying to obtain the same result with throwable.printStackTrace() and objectMapper.writeValueAsString(runtimeException). Execute 'e.printStackTrace()' and you
ll erhalten die gleiche "komisch und unvollständig" aus. Bitte, ändern Sie die Letzte Zeile in Ihrem code ' - System.aus.println( objectMapper.writeValueAsString( throwable ) ); " und überprüfen Sie die Ausgabe.objectMapper.writeValueAsString(runtimeException)
ich bin nicht Deserialisieren derThrowable
an alle-es ist nur die serialisierte Ausgabe. Betrachten wir ein Szenario, wo ich zu serialisieren derThrowable
auf der server-Seite, übertragen der serialisierten Ausgabe (in der form einesString
) über den Draht, und dann deserialisiert es auf der client-Seite (mitobjectMapper.readValue
- Methode). Der client sollte in der Lage sein, um das vollständigeThrowable
Informationen nach ist es deserialisiert werden.m asking you to add 'objectMapper.writeValueAsString( throwable )', not 'objectMapper.writeValueAsString( runtimeException )'. Do you see the difference? You
neu aufrufen throwable.printStackTrace(), die nicht geben Ihnen das gewünschte Ergebnis. Die Deserialisierung funktioniert einwandfrei. Ihr versucht, um das Ergebnis in einer falschen Art und Weise. So ENTFERNEN Sie 'throwable.printStackTrace()' in deinem code und fügen Sie 'objectMapper.writeValueAsString( throwable )' (NICHT runtimeException).Dies wird drucken Sie eine vollständige Informationen für Ihr Objekt DESERIALISIERT.objectMapper.writeValueAsString(throwable)
(nachdem es deserialisiert), aber die Ausgabe nicht mit dem deklarieren der Klasse; es ist leer (das ist ähnlich wie das drucken der stack-trace). Klar, ich will dieThrowable
Objekt zu drucken, das gleiche stack-trace vor der Serialisierung und nach der Deserialisierung. Ich bin nämlich der Deserialisierung nicht funktionieren, da der stack-trace nicht in Ihrer Gesamtheit zu erhalten.Scheint es, dass die Ausgabe, die man in der version 2.2.1 ist nicht das selbe bekommen wie ich mit der version 2.2.0 (die laut der website ist die neueste 2.x-version). Neben den neuesten verfügbaren 2.x-version auf dem Maven-Repository ist 2.2.2. Also ich würde versuchen, entweder downgrade es auf 2.2.0 oder ein upgrade auf 2.2.2. Wenn die änderungen, die Sie bringt das erwartete Ergebnis, ich würde noch weiter gehen mit dieser version, und öffnen Sie einen FEHLER in Jacksons JIRA.
Und natürlich nicht zu vergessen
aus Michaels Antwort.
SerializationConfig.Feature
entspricht der alten Paketstruktur (vor version 2.0). Ich habe versucht, das auskommentieren der beiden Zeilen, wie Sie vorgeschlagen (während der Serialisierung, Deserialisierung, und die andere Kombinationen möglich), aber kein Glück. Die deserialisiertThrowable
nicht enthalten, die deklarieren der Klasse. Und, ich benutze Java 7 (das sollte keine Rolle viel, obwohl).Ich habe ein ähnliches Problem. Ich bin mit diesem code jetzt, und es erlaubt mir, zu serialisieren und Deserialisieren von Ausnahmen mit der richtigen Arten (D. H. eine
RuntimeException
wird einRuntimeException
wieder :)):Bin ich mit der Manipulation der
BeanDeserializerFactory
zu machenbuildThrowableDeserializer
nicht behandelnThrowable
alle besonderes, aber genau wie jede andereObject
. Dann mitMixins
zu definieren, der "Besondere" Umgang mitThrowable
undStackTraceElement
nach meinem Geschmack.Ist es so notwendig, um die Verwendung der json-Serialisierung? Sieht liks gibt es einige bugs mit throwables. Warum nicht mit system-api:
Versuchen Polymorphismus, so dass jackson deserializer weiß, welche Art von Throwable zu erstellen: