在 Spring Boot RestAPI 响应中排除空的 Hateoas“链接”

问题描述 投票:0回答:3

我有一个扩展 RepresentationModel 的示例响应类。在某些情况下,我不会在响应中添加任何 hatoas 链接。在这种情况下,我在 json 响应中得到一个空的链接字段

“链接”:[]

我尝试向响应类添加“JsonInclude.Include.NON_EMPTY”,但由于链接字段在 RepresentationModel 中是最终的,因此它仍然在响应中引入空链接字段。

如何避免响应中出现此空链接字段?

json spring-hateoas hateoas
3个回答
2
投票

首先确保您有充分的理由使用媒体类型

application/json
的链接,而不是为超媒体构建的媒体类型,例如HAL (
application/hal+json
)。

虽然

RepresentationModel
有一个
List<Link>
字段,但 getter 返回
Links
而不是
List<Link>
。 Jackson 将其视为简单类型(其中使用
JsonSerializer
)而不是集合类型(其中使用
CollectionSerializer
),因此
JsonInclude.Include.NON_EMPTY
无法按您的预期工作。

public class RepresentationModel<T extends RepresentationModel<? extends T>> {

    private final List<Link> links;

    @JsonProperty("links")
    public Links getLinks() {
        return Links.of(links);
    }
}

public class Links implements Iterable<Link> { }

public abstract class JsonSerializer<T> {
    public boolean isEmpty(SerializerProvider provider, T value) {
        return (value == null);
    }
}

public class CollectionSerializer {
    @Override
    public boolean isEmpty(SerializerProvider prov, Collection<?> value) {
        return value.isEmpty();
    }
}

一种解决方案是覆盖 getter

getLinks()
并使用自定义过滤器。

class User extends RepresentationModel<User> {

    // ...

    @JsonProperty("links")
    // if links is an empty JSON array, exclude it
    @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = EmptyLinksFilter.class)
    @Override
    public Links getLinks() {
        return super.getLinks();
    }
}

/* The word "filter" is a bit ambiguous (included? or excluded?).
Here when the equals() of this class return true, the value will be excluded. 
Choose a class name to make yourself comfortable. */
class EmptyLinksFilter{

    @Override
    public boolean equals(Object obj) {

        if (obj == null || !(obj instanceof Links)) {
            return false;
        }
        Links links = (Links) obj;
        return links.isEmpty();
    }
}

完整代码位于Github

第二个解决方案可能是自定义 mixin,就像 Spring HATEOAS 已经为 HAL 构建的那样。相关代码有:

  • RepresentationModelMixin
  • Jackson2HalModule.HalLinkListSerializer
  • Jackson2Hal 模块
  • HalMediaType配置

第二种解决方案要复杂得多。这就是为什么我推荐像 HAL 这样的媒体类型,Spring HATEOAS 已经为此提供了良好的配置。


1
投票

根据@yejianfengblue的回答,我创建了一个自定义表示模型,如下所示,并从响应java类而不是Hateoas

CustomRepresentationModel
扩展了这个
RepresentationModel

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.hateoas.Links;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.lang.NonNull;

public class CustomRepresentationModel<T extends CustomRepresentationModel<? extends T>> extends
    RepresentationModel<T> {

  @JsonProperty("_links")
  @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = NonEmptyLinksFilter.class)
  @NonNull
  @Override
  public Links getLinks() {
    return super.getLinks();
  }

  static class NonEmptyLinksFilter {

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof Links)) {
        return false;
      }
      Links links = (Links) obj;
      return links.isEmpty();
    }

    @Override
    public int hashCode() {
      return super.hashCode();
    }
  }

}

0
投票

2024 年更新,使用 Spring boot 的 openapi 生成器,我使用 swagger.yaml,然后在 pom.xml 上,我刚刚添加了注释 Jackson 非空,它可以工作:

<additionalModelTypeAnnotations>@com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY)
                            </additionalModelTypeAnnotations>

之后我的空链接不会放入创建的 Json 中

© www.soinside.com 2019 - 2024. All rights reserved.