2015-11-18 41 views
1

一个非常快速的问题,似乎没有简单的答案。在Spring中嵌入对象而不是集合HATEOAS

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

回答

1

参数enforceEmbeddedCollections在这个构造允许表示像对象一样的嵌入式数组。

public HalHandlerInstantiator(RelProvider resolver, CurieProvider curieProvider, boolean enforceEmbeddedCollections) {}   

所以,你应该设置值为false的HalHandlerInstantiator。 有一个小例子:

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

添加下面的代码片段到你@Configuration类之一。此处的代码与org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar中的代码类似。我们基本上覆盖了HAL-ObjectMapper中的HalHandlerInstantiator,我们将false传递给enforceEmbeddedCollections参数。这是一个肮脏的黑客攻击,但是目前还没有办法配置这个春天 - 仇恨机器的这个方面。

@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; 
     } 
    }; 
}