一个非常快速的问题,似乎没有简单的答案。
是否可以使用Spring HATEOAS将对象直接放在嵌入式资源下? JSON中所需的输出格式应该类似于
{
...
_embedded: {
myObject: {
...
}
}
}
使用下面的代码,我总是会收集我想要嵌入的任何资源。
ArrayList<Resource<?>> embeddedContent = new ArrayList<>();
Resource<MyObject> myObjectResource = new Resource<MyObject>(new MyObject());
embeddedContent.add(myObjectResource );
Resources<Resource<?>> embeddedResources = new Resources<Resource<?>>(embeddedContent);
然后将embeddedResources
放在一个类上,该类稍后也会映射到一个资源。
但由于某些原因,即使我没有向嵌入式资源添加集合,输出仍然将myObject
嵌入资源显示为数组:
{
...
_embedded: {
myObject: [
{
...
}
]
}
}
答案 0 :(得分:1)
此构造函数中的参数 enforceEmbeddedCollections 允许表示嵌入式数组,如对象。
public HalHandlerInstantiator(RelProvider resolver, CurieProvider curieProvider, boolean enforceEmbeddedCollections) {}
因此,您应该将HalHandlerInstantiator设置为值false。 有一个小例子:
ObjectMapper halObjectMapper = new ObjectMapper();
halObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
halObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
halObjectMapper
.setHandlerInstantiator(new Jackson2HalModule.
HalHandlerInstantiator(new DefaultRelProvider(), null, false));
Jackson2HalModule jackson2HalModule = new Jackson2HalModule();
halObjectMapper.registerModule(jackson2HalModule);
try {
halObjectMapper.writeValueAsString(new Resources<Album>(Arrays.asList(new Album("1", "title", "1", 1))));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
答案 1 :(得分:1)
将以下代码段添加到您的@Configuration
个类之一。此处的代码与org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar
中的代码类似。我们基本上覆盖了HAL-ObjectMapper中的HalHandlerInstantiator
,我们将false
传递给enforceEmbeddedCollections
参数。这是一个肮脏的黑客,但目前还没有办法配置spring-hateoas机器的这个方面。
@Bean
BeanPostProcessor halModuleReconfigurer(BeanFactory beanFactory) {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
adapter.setMessageConverters(reconfigureObjectMapper(adapter.getMessageConverters()));
}
if (bean instanceof AnnotationMethodHandlerAdapter) {
AnnotationMethodHandlerAdapter adapter = (AnnotationMethodHandlerAdapter) bean;
List<HttpMessageConverter<?>> augmentedConverters = reconfigureObjectMapper(Arrays.asList(adapter
.getMessageConverters()));
adapter
.setMessageConverters(augmentedConverters.toArray(new HttpMessageConverter<?>[augmentedConverters.size()]));
}
if (bean instanceof RestTemplate) {
RestTemplate template = (RestTemplate) bean;
template.setMessageConverters(reconfigureObjectMapper(template.getMessageConverters()));
}
return bean;
}
private List<HttpMessageConverter<?>> reconfigureObjectMapper(final List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter halConverterCandidate = (MappingJackson2HttpMessageConverter) converter;
ObjectMapper objectMapper = halConverterCandidate.getObjectMapper();
if (Jackson2HalModule.isAlreadyRegisteredIn(objectMapper)) {
final CurieProvider curieProvider = Try.of(() -> beanFactory.getBean(CurieProvider.class)).getOrElse((CurieProvider) null);
final RelProvider relProvider = beanFactory.getBean("_relProvider", RelProvider.class);
final MessageSourceAccessor linkRelationMessageSource = beanFactory.getBean("linkRelationMessageSource", MessageSourceAccessor.class);
objectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider, linkRelationMessageSource, false));
}
}
}
return converters;
}
};
}