我有一个包含多个@RestController
类的Spring Boot Web应用程序。
我喜欢我的REST控制器返回的默认json格式。
为了在我的DAO bean(使用json序列化和反序列化)中使用,我创建了一个自定义ObjectMapper
:
@Configuration
public class Config{
@Bean
public ObjectMapper getCustomObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
return objectMapper;
}
}
在我的每个DAO课程中,我都会自动调整我的自定义ObjectMapper
:
@Repository
@Transactional
public class MyDaoImpl implements MyDao {
@Autowired
ObjectMapper objectMapper
//Dao implementation...
}
一切正常。问题是我的自定义ObjectMapper
被Spring自动选中并用于序列化REST响应
这是不可取的。对于REST控制器,我想保留Spring默认创建的ObjectMapper
。
如何判断Spring Boot 不检测并不使用我的自定义ObjectMapper
bean进行内部工作?
答案 0 :(得分:1)
您可以提供标准的ObjectMapper和自定义对象映射器,并将标准设置为df.loc[df.B.ne('one'),['B','D']]
Out[207]:
B D
2 two 0.742752
3 three -1.264271
4 two -0.112787
5 two 0.667358
7 three -0.213575
。
然后为您的自定义ObjectMapper命名,并将其与@Qualifier注释一起使用。
@Primary
现在您可以引用自定义映射器
@Configuration
public class Config{
//This bean will be selected for rest
@Bean
@Primary
public ObjectMapper stdMapper(){
return new ObjectMapper();
}
//You can explicitly refer this bean later
@Bean("customObjectMapper")
public ObjectMapper getCustomObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
return objectMapper;
}
}
@Repository @Transactional public class MyDaoImpl implements MyDao { @Autowired @Qualifier("customObjectMapper") ObjectMapper objectMapper //Dao implementation... }
将同时执行@Autowired和@Resource("custonmObjectMapper")
答案 1 :(得分:0)
您可以创建:
public class MapperUtils {
private static final ObjectMapper mapper = new ObjectMapper();
public static <T> T parseResponse(byte[] byteArrray, Class<T> parseType) throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(byteArrray, parseType);
}
}
ObjectMapper
是线程安全的。但是,由于性能问题(Should I declare Jackson's ObjectMapper as a static field?),有些人不鼓励使用单个实例。
答案 2 :(得分:0)
由于我不想触摸Spring的默认ObjectMapper
,因此无法创建@Primary
ObjectMapper
来遮盖Spring的默认ObjectMapper
。
相反,我最终要做的是创建一个BeanFactoryPostProcessor
,它在Spring的上下文中注册了一个自定义的非主要ObjectMapper
:
@Component
public class ObjectMapperPostProcessor implements BeanFactoryPostProcessor {
public static final String OBJECT_MAPPER_BEAN_NAME = "persistenceObjectMapper";
@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) {
final AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(ObjectMapper.class, this::getCustomObjectMapper)
.getBeanDefinition();
// Leave Spring's default ObjectMapper (configured by JacksonAutoConfiguration)
// as primary
beanDefinition.setPrimary(false);
final AutowireCandidateQualifier mapperQualifier = new AutowireCandidateQualifier(PersistenceObjectMapper.class);
beanDefinition.addQualifier(mapperQualifier);
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(OBJECT_MAPPER_BEAN_NAME, beanDefinition);
}
private ObjectMapper getCustomObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
return objectMapper;
}
}
从上面的代码中可以看出,我还为自定义ObjectMapper
bean分配了一个限定符。
我的限定词是一个用@Qualifier
注释的注释:
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface PersistenceObjectMapper {
}
然后我可以使用我的自定义注释自动为我的自定义ObjectMapper
接线,
@Repository
public class MyDao {
@Autowired
public MyDao(DataSource dataSource, @PersistenceObjectMapper ObjectMapper objectMapper) {
// constructor code
}
答案 3 :(得分:0)
Simone Pontiggia 答案是正确的方向。您应该创建一个 @Primary bean,Spring将在其内部使用它,然后创建自己的ObjectMapper bean,并使用 @Qualifier 将它们自动连线。
这里的问题是,创建默认的bean像这样:
@Bean
@Primary
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
实际上无法按预期工作,因为Spring默认的ObjectMapper具有其他配置。 创建将由spring使用的默认ObjectMapper的正确方法是:
@Bean
@Primary
public ObjectMapper objectMapper() {
return Jackson2ObjectMapperBuilder.json().build();
}
您可以在以下位置找到有关Spring默认ObjectMapper的更多信息:https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html在 79.3 Customize the Jackson ObjectMapper
下