Warum funktioniert die polymorphe Jackson-Serialisierung nicht in Listen?

8

Jackson macht etwas wirklich Bizarres und ich kann keine Erklärung dafür finden. Ich mache polymorphe Serialisierung und es funktioniert perfekt, wenn ein Objekt für sich allein ist. Wenn Sie jedoch dasselbe Objekt in eine Liste einfügen und stattdessen die Liste serialisieren, wird die Typinformation gelöscht.

Die Tatsache, dass es Typinformationen verliert, würde zu einem Typlöschen führen. Dies geschieht jedoch während der Serialisierung des Inhalts der Liste; Alles, was Jackson tun muss, ist das aktuelle Objekt, das serialisiert wird, zu inspizieren, um seinen Typ zu bestimmen.

Ich habe ein Beispiel mit Jackson 2.5.1 erstellt:

%Vor%

Hier ist die Ausgabe:

%Vor%

Wie Sie sehen, fügt Jackson die Typinformationen nicht hinzu, wenn sich das Objekt in einer Liste befindet. Weiß jemand, warum das passiert?

    
monitorjbl 10.12.2015, 03:26
quelle

3 Antworten

13

Die verschiedenen Gründe, warum dies passiert, werden hier und hier . Ich stimme nicht unbedingt mit den Gründen überein, aber Jackson, wegen der Typauslöschung, kennt nicht die Art der Elemente List enthält. Es wählt einen einfachen Serializer, der Ihre Anmerkungen nicht interpretiert.

Sie haben zwei Optionen in diesen Links vorgeschlagen:

Zunächst können Sie eine Klasse erstellen, die Collection implementiert, sie instanziieren und die Instanz serialisieren.

%Vor%

Das Argument des generischen Typs Map ist nicht verloren. Jackson hat Zugriff darauf und benutzt es.

Zweitens können Sie eine List<Cat> für den Typ Cat instanziieren und verwenden. Zum Beispiel

%Vor%

wird gedruckt

%Vor%     
Sotirios Delimanolis 10.12.2015, 05:30
quelle
11

Die Antwort, die Sotirios Delimanolis gab, ist die richtige. Ich dachte jedoch, es wäre nett, diese Problemumgehung als separate Antwort zu veröffentlichen. Wenn Sie sich in einer Umgebung befinden, in der Sie den ObjectMapper nicht für jede Art von Sache ändern können, die Sie zurückgeben müssen (wie eine Jersey / SpringMVC-Webanwendung), gibt es eine Alternative.

Sie können einfach ein privates abschließendes Feld in die Klasse einfügen, die den Typ enthält. Das Feld ist für nichts außerhalb der Klasse sichtbar, aber wenn Sie es mit @JsonProperty("@type") (oder "@class" oder wie auch immer Ihr Typfeld benannt ist) annotieren, wird Jackson es unabhängig davon, wo sich das Objekt befindet, serialisieren.

%Vor%     
monitorjbl 10.12.2015 13:59
quelle
0

Da Arrays keine Typlöschung verwenden, können Sie sie lösen, indem Sie die ObjectMapper.writeValueAsString überschreiben, um die Sammlung in ein Array umzuwandeln.

%Vor%

Verwenden Sie es in Ihrem Test.main:

%Vor%

Ausgabe (Katzen und Hunde Liste):

%Vor%     
pdorgambide 20.02.2017 09:47
quelle

Tags und Links