问题描述
我有一个扩展RepresentationModel的示例响应类。在某些情况下,我不会在响应中添加任何仇恨链接。在这种情况下,我在json响应中得到一个空链接字段
“链接”:[]
我尝试在响应类中添加“ JsonInclude.Include.NON_EMPTY”,但是由于links字段在RepresentationModel中是最终的,因此它仍然在响应中带来了空的links字段。
如何避免响应中的空白链接字段?
解决方法
首先请确保您有充分的理由使用媒体类型为application/json
而不是media type built for hypermedia的链接,例如HAL(application/hal+json
)。
尽管RepresentationModel
的字段为List<Link>
,但getter返回Links
而不是List<Link>
。杰克逊将其视为简单类型(使用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();
}
}
一种解决方案是覆盖吸气剂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中。
第二个解决方案可能是自定义混合,就像Spring HATEOAS已经为HAL构建的一样。相关代码为:
- RepresentationModelMixin
- Jackson2HalModule.HalLinkListSerializer
- Jackson2HalModule
- HalMediaTypeConfiguration
第二种解决方案非常复杂。这就是为什么我建议像HAL这样的媒体类型,对于这些类型,Spring HATEOAS已经具有良好的配置。
,根据@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();
}
}
}