2015-11-18 47 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; 
     } 
    }; 
}