Deserialisieren von JSON mit Jackson - Warum JsonMappingException "Kein passender Konstruktor"?
Ich habe ein problem Deserialisieren einen JSON-string mit Jackson (aber ich habe kein problem mit der Serialisierung ein Objekt zu JSON).
Unten präsentiere ich die Klassen die ich verwende. Das problem kommt, wenn ich rececive ein JSON-string (eine ProtocolContainer, die serialisiert wurde an anderer Stelle und abgerufen via webservice) und de-Serialisierung:
JSON-string:
{"DataPacketJSONString":null,"DataPacketType":"MyPackage.DataPackets.LoginRequestReply","MessageId":6604,"SenderUsername":null,"SubPacket":{"__type":"LoginRequestReply:#MyPackage.DataPackets","Reason":"Falschen pass oder Benutzername","Success":false,"Username":"User1"}}
Ich versuche zu Deserialisieren wie diese:
ProtocolContainer ret = ProtocolContainer.Create(jsonString);
und der code, der ausgeführt wird in ProtocolContainer kann unten gesehen werden. Ausnahme:
org.codehaus.jackson.Karte.JsonMappingException: Nein geeignet Konstruktor
gefunden für [einfache Art, Klasse
MeinPaket.ProtocolContainer]: können Sie nicht
instanziieren von JSON-Objekt (hinzufügen/aktivieren geben Sie die Informationen?)
[Quelle: java.io.StringReader@4059dcb0; Zeile: 1, Spalte: 2]
Ich würde wirklich zu schätzen einige hier eingeben =) Thx!!!
ProtocolContainer.java - eine container-Klasse, kapselt meine "SubPackets":
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import MyPackage.DataPackets.*;
public class ProtocolContainer
{
public String SenderUsername;
public String DataPacketType;
public long MessageId;
public String DataPacketJSONString;
public DataPacket SubPacket;
public ProtocolContainer(DataPacket dp)
{
DataPacketType = dp.getClass().toString().substring(6);
SubPacket = dp;
}
public String toJSON()
{
try {
if (SubPacket != null)
this.DataPacketJSONString = ProtocolContainer.mapper.writeValueAsString(SubPacket);
return ProtocolContainer.mapper.writeValueAsString(this);
} catch (JsonGenerationException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static ObjectMapper mapper = new ObjectMapper();
public static ProtocolContainer Create(String jsonString)
{
ProtocolContainer pc = null;
try {
pc = mapper.readValue(jsonString, ProtocolContainer.class); //error here!
} catch (JsonParseException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
//TODO Auto-generated catch block
e.printStackTrace(); //Exception when deserializing
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
try
{
if (pc != null && pc.DataPacketType == "LoginRequest")
pc.SubPacket = mapper.readValue(jsonString, LoginRequest.class);
}
catch (JsonParseException e)
{
e.printStackTrace();
}
catch (JsonMappingException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return pc;
}
}
DataPacket.java - eine Superklasse für alle meine Datenpaketen befassen
public class DataPacket
{
}
LoginRequestReply.java - ein Datenpaket
package MyPackage.DataPackets;
import MyPackage.DataPacket;
public class LoginRequestReply extends DataPacket
{
public boolean LoginOK;
public int UserId;
}
InformationsquelleAutor der Frage Ted | 2011-12-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Fehlermeldungen sagt es allen, Ihre ProtocolContainer nicht über eine default-Konstruktor, so dass Jackson nicht in der Lage ist, eine Instanz davon erstellt werden. (Da die nur den aktuellen Weg der Schaffung eines ProtocolContainer ist durch die übergabe eines Datenpakets.)
InformationsquelleAutor der Antwort Ola Herrdahl
In diesem Fall, könnte man hinzufügen
@JsonCreator
Anmerkung zum Konstruktor. Es gibt zwei Möglichkeiten, es getan werden könnte:@JsonProperty
Anmerkung, bevor das argument, dann JSON-Eigenschaft passenden Namen übergeben an den Konstruktor (annotation ist zwingend notwendig, da Java-byte-code enthält NICHT den Namen der Methode oder Konstruktor-Argumente) - ich vermute, Sie wollen@JsonProperty("SubPacket")
Funktioniert dies, wenn die notwendigen Informationen für den Konstruktor kommt von JSON. Wenn nicht, müssen Sie hinzufügen alternativer no-arg-Konstruktor.
Durch die Art und Weise, die Fehlermeldung klingt falsch in diesem Fall. Es sollte nur verabreicht werden, wenn die JSON-Daten matching erwarteten Wert, wenn ein JSON-String.
InformationsquelleAutor der Antwort StaxMan
Daumenregel: Fügen Sie eine default-Konstruktor für jede Klasse, die Sie als eine mapping-Klasse. Sie verpasste dieses und Problem auftauchen!
Fügen Sie einfach einen Standard-Konstruktor und es sollte funktionieren.
InformationsquelleAutor der Antwort Badal
Ich Stand vor dem Problem und keine der Antworten, die für mich gearbeitet. es scheint, die Ausnahme, ist sehr generisch und ist geworfen für n verschiedene Ursachen. So ein Update kann nicht für alle funktionieren.
Mein Fall:
wir haben eine json-Antwort, in der Kreditkarte ist ein komplexer Typ, aber optional. wenn es keine Kreditkarten-Daten, wir waren immer einen leeren string in der Antwort:
"creditcard":""
Aber Kreditkarte ist ein komplexer Typ für uns:
Haben wir herausgefunden, dass, wenn es keine Kreditkarten-Daten, wir sollten so etwas in der json-Antwort:
"creditcard":{}
und nicht "creditcard":""
es das Problem behoben.
InformationsquelleAutor der Antwort vks
Andere Möglichkeit, wenn Sie Lombok! Ich habe nicht herausgefunden, weshalb.
Wenn lombok Konstruktor annotation verwendet wird, an der äußeren Klasse die innere Klasse auch wenn man schreibt alle args-Konstruktor manuell, es beschwert sich trotzdem den Konstruktor nicht gefunden werden kann. Wenn Sie
@AllArgsConstructor
aufMaintenance
statt zu schreiben Ihre eigenen, jackson würde deserialise erfolgreich. Ich habe die gleiche Erfahrung heute, hinzufügen@AllArgsConstructor
löst.InformationsquelleAutor der Antwort Tiina