问题
I have a multitude of classes coming from a vendor that like to randomly throw RuntimeExceptions on property access.
public Object getSomeProperty() {
if (!someObscureStateCheck()) {
throw new IllegalStateExcepion();
}
return calculateTheValueOfProperty(someRandomState);
}
I cannot change the classes, cannot add annotations and it's unrealistic to define mixins for every single class as this part of stack changes fairly often.
How do I make Jackson ignore a property if its getter throws an Exception?
回答1:
To perform custom serialization in Jackson, you can register a module with a BeanSerializerModifier that specifies whatever modifications are needed. In your case, BeanPropertyWriter.serializeAsField is the method responsible for serializing individual fields, so you should make your own BeanPropertyWriter
that ignores exceptions on field serialization, and register a module with a BeanSerializerModifier
that uses changeProperties to replace all default BeanPropertyWriter
instances with your own implementation. The following example demonstrates:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.*;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public class JacksonIgnorePropertySerializationExceptions {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule().setSerializerModifier(new BeanSerializerModifier() {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
return beanProperties.stream().map(bpw -> new BeanPropertyWriter(bpw) {
@Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
try {
super.serializeAsField(bean, gen, prov);
} catch (Exception e) {
System.out.println(String.format("ignoring %s for field '%s' of %s instance", e.getClass().getName(), this.getName(), bean.getClass().getName()));
}
}
}).collect(Collectors.toList());
}
}));
mapper.writeValue(System.out, new VendorClass());
}
public static class VendorClass {
public String getNormalProperty() {
return "this is a normal getter";
}
public Object getProblematicProperty() {
throw new IllegalStateException("this getter throws an exception");
}
public String getAnotherNormalProperty() {
return "this is a another normal getter";
}
}
}
The above code outputs the following, using Jackson 2.7.1 and Java 1.8:
ignoring java.lang.reflect.InvocationTargetException for field 'problematicProperty' of JacksonIgnorePropertySerializationExceptions$VendorClass instance
{"normalProperty":"this is a normal getter","anotherNormalProperty":"this is a another normal getter"}
showing that getProblematicProperty
, which throws an IllegalStateException
, will be omitted from the serialized value.
来源:https://stackoverflow.com/questions/35359430/how-to-make-jackson-ignore-properties-if-the-getters-throw-exceptions