Serialisieren Sie nur Felder, die mit Jackson ein benutzerdefiniertes Kriterium erfüllen
1. Überblick
Dieses Tutorial wird veranschaulichen, wie wiruse Jackson to only serialize a field if it meets a specific, custom criteria können.
Angenommen, wir möchten einen ganzzahligen Wert nur dann serialisieren, wenn er positiv ist. Wenn dies nicht der Fall ist, möchten wir ihn vollständig überspringen.
Wenn Sie tiefer graben undother cool things you can do with the Jackson 2 lernen möchten, gehen Sie zuthe main Jackson tutorial.
2. Verwenden Sie Jackson Filter, um den Serialisierungsprozess zu steuern
Zuerst müssen wir den Filter für unsere Entität mithilfe der Annotation@JsonFilterdefinieren:
@JsonFilter("myFilter")
public class MyDto {
private int intValue;
public MyDto() {
super();
}
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
}
Dann müssen wir unsere benutzerdefiniertenPropertyFilter definieren:
PropertyFilter theFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!writer.getName().equals("intValue")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
int intValue = ((MyDtoWithFilter) pojo).getIntValue();
if (intValue >= 0) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
Dieser Filter enthält die tatsächliche Logik, die basierend auf ihrem Wert entscheidet, ob das FeldintValueserialized or not sein soll.
Als nächstes verknüpfen wir diesen Filter mitObjectMapper und serialisieren eine Entität:
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", theFilter);
MyDto dtoObject = new MyDto();
dtoObject.setIntValue(-1);
ObjectMapper mapper = new ObjectMapper();
String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);
Und schließlich können wir überprüfen, ob das FeldintValuetatsächlichnot part of the marshalled JSON output ist:
Lassen Sie uns nun diskutieren, wie Objekte beim Serialisieren basierend auf der Eigenschaftvalue übersprungen werden. Wir werden alle Objekte überspringen, bei denen die Eigenschafthiddentrue ist:
3.1. Versteckbare Klassen
Schauen wir uns zunächst dieHidable-Schnittstelle an:
@JsonIgnoreProperties("hidden")
public interface Hidable {
boolean isHidden();
}
Und wir haben zwei einfache Klassen, die diese SchnittstellePerson,Address implementieren:
Person Klasse:
public class Person implements Hidable {
private String name;
private Address address;
private boolean hidden;
}
UndAddress Klasse:
public class Address implements Hidable {
private String city;
private String country;
private boolean hidden;
}
Hinweis: Wir haben@JsonIgnoreProperties(“hidden”) verwendet, um sicherzustellen, dass die Eigenschafthiddenelbst nicht in JSON enthalten ist
3.2. Benutzerdefinierter Serializer
Weiter - hier ist unser benutzerdefinierter Serializer:
public class HidableSerializer extends JsonSerializer {
private JsonSerializer
Beachten Sie, dass:
Wenn das Objekt nicht übersprungen wird, delegieren wir die Serialisierung an den standardmäßigen Serialisierer mit Injection.
Wir haben die MethodeisEmpty() überschrieben - um sicherzustellen, dass im Fall eines versteckten Objekts eine Eigenschaft ist, wird der Eigenschaftsname auch von JSON ausgeschlossen.
3.3. Verwenden vonBeanSerializerModifier
Schließlich müssen wirBeanSerializerModifier verwenden, um den Standard-Serializer in unsere benutzerdefiniertenHidableSerializer einzufügen - wie folgt:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_EMPTY);
mapper.registerModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer> modifySerializer(
SerializationConfig config, BeanDescription desc, JsonSerializer> serializer) {
if (Hidable.class.isAssignableFrom(desc.getBeanClass())) {
return new HidableSerializer((JsonSerializer) serializer);
}
return serializer;
}
});
}
});
3.4. Beispielausgabe
Hier ist ein einfaches Serialisierungsbeispiel:
Address ad1 = new Address("tokyo", "jp", true);
Address ad2 = new Address("london", "uk", false);
Address ad3 = new Address("ny", "usa", false);
Person p1 = new Person("john", ad1, false);
Person p2 = new Person("tom", ad2, true);
Person p3 = new Person("adam", ad3, false);
System.out.println(mapper.writeValueAsString(Arrays.asList(p1, p2, p3)));
@Test
public void whenNotHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", false);
Person person = new Person("john", ad, false);
String result = mapper.writeValueAsString(person);
assertTrue(result.contains("name"));
assertTrue(result.contains("john"));
assertTrue(result.contains("address"));
assertTrue(result.contains("usa"));
}
Als nächstesonly address is hidden:
@Test
public void whenAddressHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", true);
Person person = new Person("john", ad, false);
String result = mapper.writeValueAsString(person);
assertTrue(result.contains("name"));
assertTrue(result.contains("john"));
assertFalse(result.contains("address"));
assertFalse(result.contains("usa"));
}
Nunentire person is hidden:
@Test
public void whenAllHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", false);
Person person = new Person("john", ad, true);
String result = mapper.writeValueAsString(person);
assertTrue(result.length() == 0);
}
4. Fazit
Diese Art der erweiterten Filterung ist unglaublich leistungsfähig und ermöglicht eine sehr flexible Anpassung des JSON bei der Serialisierung komplexer Objekte mit Jackson.
Eine flexiblere, aber auch komplexere Alternative wäre die Verwendung eines vollständig benutzerdefinierten Serializers zur Steuerung der JSON-Ausgabe. Wenn diese Lösung also nicht flexibel genug ist, lohnt es sich möglicherweise, dies zu prüfen.
Die Implementierung all dieser Beispiele und Codefragmentecan be found in my github project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.