2017-10-21 6 views
1

Ich habe eine abstrakte Klasse Fahrzeug:Jackson Filter und Polymorphie

@JsonFilter('Vehicle_Filter') 
public abstract class Vehicle { 
    private String brand; 
    private int nbOfWheels; 
    //Other attributes, constructor & methods 
} 

ich ein Kind Klasse haben Auto Verlängerung Fahrzeug:

@JsonFilter('Car_Filter') 
public class Car extends Vehicle { 
    private int nbOfDoors; 
    private boolean isElectric; 
    //Other attributes, constructor & methods 
} 

Und ich habe ein anderes Kind Klasse Fahrrad Verlängerung Fahrzeug:

@JsonFilter('Bike_Filter') 
public class Bike extends Vehicle { 
    private double tirePressure; 
    private boolean isAllTerrain; 
    //Other attributes, constructor & methods 
} 

Lassen Sie uns sagen, dass ich eine Klasse VehicleCollection die eine Liste der Fahrzeuge Ich möchte in einer HTML-Seite angezeigt werden:

@JsonFilter('VehicleCollection_Filter') 
public abstract class VehicleCollection { 
    private List<Vehicle> vehicles; 
    //Other attributes, constructor & methods 
} 

Dafür ich es mit Jackson serialisiert werden (von fasterXML). Angenommen, ich möchte nur einige Attribute für jedes Fahrzeug anzeigen. Ich werde eine FilterProvider Schnittstelle verwenden.

Die Frage ist: Wenn ich ein Fahrzeugattribut filtern will, möchte ich nicht unterscheiden, ob es ein Fahrrad oder ein Auto ist. Alles, was zählt, ist, dass es ein Fahrzeug ist. Ich dachte, ich mit, dass einfiel beim Filtern:

FilterProvider filterProvider = new SimpleFilterProvider() 
      .addFilter("VehicleCollection_Filter", SimpleBeanPropertyFilter.filterOutAllExcept("vehicles")) 
      .addFilter("Vehicle_Filter", SimpleBeanPropertyFilter.filterOutAllExcept("brand", "nbOfDoors", "isElectric")); 

... Aber wenn die Schriftsteller Aufruf dieser Fehler ausgelöst wird: Could not find filter with id: 'Car_Filter'. Es scheint, dass Jackson nicht über Polymorphismus hören will ...

Hat jemand das gleiche Problem gehabt? Wenn ja, kann ich einen Hinweis darauf haben, wie ich es überwinden kann? Und wenn nein, gibt es eine Dokumentation oder eine implizite Erklärung darüber, warum Jackson Filter nicht mit Vererbung umgehen können?

+0

Wenn alles was zählt ist, dass es ein Fahrzeug ist Warum hast du '@JsonFilter ('Car_Filter')'? und '@JsonFilter ('Bike_Filter')'? – Oleg

+0

Weil in anderen Teilen der Anwendung ich Autos und Fahrräder getrennt anzeigen muss –

Antwort

0

Zuerst der Fehler, den Sie bekommen, ist, weil wenn Jackson eine Car Instanz serialisiert sieht es eine @JsonFilter Annotation auf der Klasse und erwartet, einen Filter mit gegebener ID durch den Filteranbieter zu finden.

Wege zu lösen:

  1. .setFailOnUnknownId(false); hinzufügen, die den Fehler zu beseitigen, sondern führen alle Felder serialisiert werden.
  2. Fügen Sie einen Standardfilter .setDefaultFilter(filterOutAllExcept("brand", "nbOfDoors", "isElectric")) hinzu, der angewendet wird, wenn "Bike_Filter" und "Car_Filter" nicht gefunden werden können. Das wird die erforderliche Ausgabe bekommen, aber mit begrenzter Flexibilität. Sie erhalten 1 Standardfilter für alle Klassen pro Filteranbieter und 1 Filter pro Klasse für alle Filteranbieter. Sie können eine Klasse nicht mit 3 Filtern annotieren, sondern zum Beispiel eine in einem Anbieter auswählen.
  3. Verwenden Sie stattdessen @JsonView. Im Gegensatz zu Filtern unterstützen Ansichten selbst die (mehrfache) Vererbung und Sie können mehr als 1 pro Feld/Getter angeben, was eine große Flexibilität bietet. Z.B .:

    abstract class Vehicle { 
        @JsonView(Detail.Basic.class) 
        private String brand; 
        @JsonView(Detail.Standard.class) 
        private int nbOfWheels; 
    } 
    
    class Car extends Vehicle { 
        @JsonView(Detail.FullCar.class) 
        private int nbOfDoors; 
        // multiple views on a field 
        @JsonView({Detail.Standard.class, Detail.Type.class}) 
        private boolean electric; 
    } 
    
    class Bike extends Vehicle { 
        @JsonView(Detail.FullBike.class) 
        private int tirePressure; 
        @JsonView({Detail.Standard.class, Detail.Type.class}) 
        private boolean allTerrain; 
    } 
    
    class Detail { 
        // marker interfaces never implemented 
        interface Basic {} 
        interface Type {} 
        interface Standard extends Basic {} 
        interface FullCar extends Basic {} 
        interface FullBike extends Basic {} 
        // 1 view can inherit from many 
        interface Full extends FullCar, FullBike {} 
    } 
    
    ObjectMapper mapper = new ObjectMapper(); 
    // only 1 view per writer 
    ObjectWriter basicWriter = mapper.writerWithView(Detail.Basic.class); 
    ObjectWriter standardWriter = mapper.writerWithView(Detail.Standard.class); 
    ObjectWriter typeWriter = mapper.writerWithView(Detail.Type.class); 
    

Ansichten sind auch weniger fehleranfällig als die Spieltypen anstelle von Strings dWenn Sie einen Tippfehler in einem Ansichtsnamen haben, hebt Ihre IDE diesen hervor. Mit @JsonFilter IDs erhalten Sie Laufzeitfehler.

Ich denke, die Tatsache, dass der Begriff „Unterklasse“docs in @JsonView erwähnt, aber nicht in @JsonFilterdocs ist so gut, eine Erklärung, wie Sie für das beobachtete Verhalten zu bekommen.

+0

Ich habe alle Lösungen ausprobiert, und alle von ihnen funktionieren! Ich habe eine Präferenz für die Verwendung der Ansichten, da es viel mehr OO ist, mehr Java;) Und auch für Leute, die es hassen, einfache Strings zu schreiben, das ist wirklich eine Erleichterung! Danke ! –