JaxbAnnotationJackson2Customizer.java
package top.infra.jackson2;
import static top.infra.jackson2.JaxbAnnotationJackson2MapperCustomizerFactory.CLASS_JAXB_ANNOTATION_INTROSPECTOR;
import static top.infra.jackson2.JaxbAnnotationJackson2MapperCustomizerFactory.CLASS_JAXB_ANNOTATION_MODULE;
import static top.infra.jackson2.JaxbAnnotationJackson2MapperCustomizerFactory.CLASS_JAXB_ANNOTATION_MODULE_PRIORITY;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import top.infra.common.ClassUtils;
import top.infra.common.EnumUtils;
/**
* see: http://wiki.fasterxml.com/JacksonJAXBAnnotations see: https://github.com/FasterXML/jackson-module-jaxb-annotations
*/
@Slf4j
public class JaxbAnnotationJackson2Customizer implements Jackson2Customizer {
@Override
public void customize(final Jackson2Properties properties, final ObjectMapper mapper) {
final Boolean isXmlMapper = this.isXmlMapper(mapper);
if (properties.getJaxb().getEnabled()) {
final Optional<Module> module = this.jaxbAnnotationModule(isXmlMapper);
module.ifPresent(mapper::registerModule);
}
}
@Override
public void customize(final Jackson2Properties properties, final Jackson2ObjectMapperBuilder builder) {
final Boolean isXmlMapper = this.isXmlMapper(builder);
if (properties.getJaxb().getEnabled()) {
final Optional<Module> jaxbAnnotationModule = this.jaxbAnnotationModule(isXmlMapper);
if (jaxbAnnotationModule.isPresent()) {
final List<Module> modules = this.modules(builder);
modules.add(jaxbAnnotationModule.get());
builder.modulesToInstall(modules.toArray(new Module[0]));
}
}
}
private Optional<Module> jaxbAnnotationModule(final Boolean isXmlMapper) {
final Optional<Module> jaxbAnnotationModule = this.jaxbAnnotationModule();
final Optional<Object> priority = this.priority(isXmlMapper);
if (jaxbAnnotationModule.isPresent() && priority.isPresent()) {
this.setJaxbAnnotationModulePriority(jaxbAnnotationModule.get(), priority.get());
}
return jaxbAnnotationModule;
}
private Optional<Module> jaxbAnnotationModule() {
try {
final Optional<Module> module;
final Optional<Class<?>> moduleClass = ClassUtils.forName(CLASS_JAXB_ANNOTATION_MODULE);
final Optional<Class<?>> introspectorClass = ClassUtils.forName(CLASS_JAXB_ANNOTATION_INTROSPECTOR);
if (moduleClass.isPresent() && introspectorClass.isPresent()) {
module = Optional.of((Module) moduleClass.get().getConstructor(introspectorClass.get()) //
.newInstance(new HackedJackson2JaxbAnnotationIntrospector()));
} else {
module = Optional.empty();
}
return module;
} catch (final ReflectiveOperationException ex) {
log.info("JaxbAnnotationModule config error", ex);
return Optional.empty();
}
}
private Optional<Object> priority(final Boolean isXmlMapper) {
final Optional<Object> priority;
final String priorityName = isXmlMapper ? "PRIMARY" : "SECONDARY";
final Class<?> enumType = ClassUtils.forName(CLASS_JAXB_ANNOTATION_MODULE_PRIORITY).orElse(null);
priority = Optional.ofNullable(enumType != null ? EnumUtils.objectValueOf(enumType, priorityName) : null);
return priority;
}
private void setJaxbAnnotationModulePriority(final Module jaxbAnnotationModule, final Object priority) {
try {
final Class<?> enumType = ClassUtils.forName(CLASS_JAXB_ANNOTATION_MODULE_PRIORITY).orElse(null);
final Method setPriorityMethod = jaxbAnnotationModule.getClass().getDeclaredMethod("setPriority", enumType);
setPriorityMethod.invoke(jaxbAnnotationModule, priority);
} catch (final ReflectiveOperationException ex) {
log.info("JaxbAnnotationModule config error", ex);
}
}
}