2

一个非常快速的问题,似乎没有简单的答案。

是否可以使用 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: [
            {
                ...
            }
        ]
    }
}
4

2 回答 2

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();
    }
于 2015-12-14T10:30:05.643 回答
1

将以下代码段添加到您的一个@Configuration类中。此处的代码看起来类似于org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar. 我们基本上覆盖了我们传递给参数HalHandlerInstantiator的 HAL-ObjectMapper 中的 。这是一个肮脏的 hack,但目前没有办法配置 spring-hateoas 机器的这方面。falseenforceEmbeddedCollections

@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;
        }
    };
}
于 2016-09-15T20:30:52.237 回答