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クラスの 1 つに次のスニペットを追加します。ここのコードは、 にあるものと似ていますorg.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar。基本的に、引数HalHandlerInstantiatorに渡す HAL-ObjectMapper の を上書きしています。これは汚いハックですが、現在、スプリングヘイト機構のこの側面を構成する方法はありません。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 に答える