How to make Jackson ignore properties if the getters throw exceptions

北城以北 提交于 2021-01-26 03:22:07

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!