如何强制Spring HATEOAS资源呈现空的嵌入式数组?

如何强制Spring HATEOAS资源呈现空的嵌入式数组?,spring,spring-hateoas,Spring,Spring Hateoas,我有以下控制器方法: @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, value = "session/{id}/exercises") public ResponseEntity<Resources<Exercise>> exercises(@PathVariable("id") Long id) { Optional<Session> opt = sessionReposito

我有以下控制器方法:

@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, value = "session/{id}/exercises")
public ResponseEntity<Resources<Exercise>> exercises(@PathVariable("id") Long id) {

  Optional<Session> opt = sessionRepository.findWithExercises(id);
  Set<Exercise> exercises = Sets.newLinkedHashSet();

  if (opt.isPresent()) {
    exercises.addAll(opt.get().getExercises());
  }

  Link link = entityLinks.linkFor(Session.class)
                         .slash(id)
                         .slash(Constants.Rels.EXERCISES)
                         .withSelfRel();

  return ResponseEntity.ok(new Resources<>(exercises, link));
}
因此,基本上没有嵌入式实体,而下面这样的东西更可取:

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/sessions/2/exercises"
        }
    }, 
    "_embedded": {
        "exercises": [] 
    }    
}

你知道如何实现这一点吗?

Spring默认使用Jackson解析器对json进行序列化/反序列化。根据Jackson的说法,它有一个名为WRITE_EMPTY_JSON_ARRAYS的功能,默认情况下它是启用的。在您的配置中,WRITE\u EMPTY\u JSON\u数组可能设置为
false
。请重新检查您的消息转换器配置。

这里的问题是,如果不付出额外的努力,就无法确定空集合是用于
练习的集合。Spring HATEOAS有一个助手类来解决这个问题:

EmbeddedWrappers wrappers = new EmbeddedWrappers(false);
EmbeddedWrapper wrapper = wrappers.emptyCollectionOf(Exercise.class);
Resources<Object> resources = new Resources<>(Arrays.asList(wrapper));
EmbeddedWrappers-wrappers=新的EmbeddedWrappers(false);
EmbeddedWrapper=wrappers.emptyCollectionOf(Exercise.class);
Resources Resources=新资源(Arrays.asList(wrapper));

EmbeddedWrapper
允许您显式地将要添加到
资源
资源
中的对象标记为嵌入式对象,甚至可以手动定义它们应该公开的rel。如上所示,帮助器还允许您将给定类型的空集合添加到
\u embedded
子句。

可以使用PagedResourceAssembler::toEmptyResource()方法。例如,以下工作:

Page<EWebProduct> products = elasticSearchTemplate.queryForPage(query, EWebProduct.class);

if(!products.hasContent()){
            PagedResources pagedResources = pageAssembler.toEmptyResource(products, WebProductResource.class,baseLink);
            return new ResponseEntity<PagedResources<WebProductResource>>(pagedResources, HttpStatus.OK);
}
Page products=elasticSearchTemplate.queryformage(query,EWebProduct.class);
如果(!products.hasContent()){
PagedResources PagedResources=pageAssembler.toEmptyResource(products,WebProductResource.class,baseLink);
返回新的响应属性(pagedResources,HttpStatus.OK);
}

我敢打赌它也适用于其他ResourceAssembler。

如果你有一个页面,你可以这样转换它:

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/sessions/2/exercises"
        }
    }
}
 public static <T> PagedModel<EntityModel<T>> toModel(PagedResourcesAssembler<T> assembler,
                                                Page<T> page) {
        if (!page.isEmpty()) {
            return assembler.toModel(page);
        } else {
            // toEmptyModel renders the _embedded field (with an empty array inside)
            return (PagedModel<EntityModel<T>>) assembler.toEmptyModel(page, TenantSubscriptionResponseDto.class);
        }
    }
publicstaticpagedmodel-toModel(PagedResourcesAssembler汇编程序,
第页(共页){
如果(!page.isEmpty()){
返回汇编程序.toModel(第页);
}否则{
//toEmptyModel渲染_嵌入字段(其中包含空数组)
return(PagedModel)assembler.toEmptyModel(page,tenantsSubscriptionResponsedTo.class);
}
}

(只需将PagedResourcesAssembler作为参数添加到控制器方法中,您就可以获得它,Spring将注入它)。

这会丢失泛型类型信息(这不是组装资源时的唯一情况)。我认为应该是
EmbeddedWrapper实现了Resource
,但Resource不是接口,在我看来,这是Spring HATEOAS中泛型问题的根源;PagedResources PagedResources=新的PagedResources(嵌入式、元数据、链接)我也偶然发现了这一点,我可以使用Object来代替embeddedWrapper的类型,但我真的不喜欢它。为什么这不是一个选项或默认值?使用SpringDataREST时,默认情况下也是空集合。@OliverGierke与其采用这种难看的解决方法,不如扩展构造函数<代码>新资源(Exercise.class、exercises等)对我来说是可以接受的。请投票支持(只需点击“添加你的反应”按钮)我很确定这不是这个,它不是JSON数组,它是Spring HATEOAS中嵌入的整个层次结构。