001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.jackson; 018 019import java.lang.reflect.Modifier; 020import java.util.Map; 021 022import javax.annotation.PostConstruct; 023 024import com.fasterxml.jackson.databind.JsonDeserializer; 025import com.fasterxml.jackson.databind.JsonSerializer; 026import com.fasterxml.jackson.databind.Module; 027import com.fasterxml.jackson.databind.module.SimpleModule; 028 029import org.springframework.beans.BeansException; 030import org.springframework.beans.factory.BeanFactory; 031import org.springframework.beans.factory.BeanFactoryAware; 032import org.springframework.beans.factory.HierarchicalBeanFactory; 033import org.springframework.beans.factory.ListableBeanFactory; 034import org.springframework.core.ResolvableType; 035 036/** 037 * Spring Bean and Jackson {@link Module} to register {@link JsonComponent} annotated 038 * beans. 039 * 040 * @author Phillip Webb 041 * @since 1.4.0 042 * @see JsonComponent 043 */ 044public class JsonComponentModule extends SimpleModule implements BeanFactoryAware { 045 046 private BeanFactory beanFactory; 047 048 @Override 049 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 050 this.beanFactory = beanFactory; 051 } 052 053 @PostConstruct 054 public void registerJsonComponents() { 055 BeanFactory beanFactory = this.beanFactory; 056 while (beanFactory != null) { 057 if (beanFactory instanceof ListableBeanFactory) { 058 addJsonBeans((ListableBeanFactory) beanFactory); 059 } 060 beanFactory = (beanFactory instanceof HierarchicalBeanFactory) 061 ? ((HierarchicalBeanFactory) beanFactory).getParentBeanFactory() 062 : null; 063 } 064 } 065 066 private void addJsonBeans(ListableBeanFactory beanFactory) { 067 Map<String, Object> beans = beanFactory 068 .getBeansWithAnnotation(JsonComponent.class); 069 for (Object bean : beans.values()) { 070 addJsonBean(bean); 071 } 072 } 073 074 private void addJsonBean(Object bean) { 075 if (bean instanceof JsonSerializer) { 076 addSerializerWithDeducedType((JsonSerializer<?>) bean); 077 } 078 if (bean instanceof JsonDeserializer) { 079 addDeserializerWithDeducedType((JsonDeserializer<?>) bean); 080 } 081 for (Class<?> innerClass : bean.getClass().getDeclaredClasses()) { 082 if (!Modifier.isAbstract(innerClass.getModifiers()) 083 && (JsonSerializer.class.isAssignableFrom(innerClass) 084 || JsonDeserializer.class.isAssignableFrom(innerClass))) { 085 try { 086 addJsonBean(innerClass.newInstance()); 087 } 088 catch (Exception ex) { 089 throw new IllegalStateException(ex); 090 } 091 } 092 } 093 } 094 095 @SuppressWarnings({ "unchecked" }) 096 private <T> void addSerializerWithDeducedType(JsonSerializer<T> serializer) { 097 ResolvableType type = ResolvableType.forClass(JsonSerializer.class, 098 serializer.getClass()); 099 addSerializer((Class<T>) type.resolveGeneric(), serializer); 100 } 101 102 @SuppressWarnings({ "unchecked" }) 103 private <T> void addDeserializerWithDeducedType(JsonDeserializer<T> deserializer) { 104 ResolvableType type = ResolvableType.forClass(JsonDeserializer.class, 105 deserializer.getClass()); 106 addDeserializer((Class<T>) type.resolveGeneric(), deserializer); 107 } 108 109}