即使与其他实体没有关系,在基本类的JSON检索上也会发生无限递归

时间:2017-11-04 15:50:56

标签: json spring hibernate spring-boot jackson

我有这个简单的类(Spring Boot + JPA / Hibernate),它只是用于测试。

class PostDetailView(DetailView):
    model = Post

    def get_queryset(self):
        return Post.objects.filter(published_date__lte=timezone.now())

class PostCreateView(LoginRequiredMixin, CreateView):
    login_url = '/login/'
    redirect_field_name = 'blog/post_detail.html'

    form_class = PostForm
    model = Post

因为默认情况下Spring RestMvc似乎正在返回@Entity @Table public class User { @Id @Column @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name="first_name") private String firstName; @Column(name="last_name") private String lastName; // getters + setters .... } ,而对于我在Ember.js中的前端客户端应用程序,我需要ContentType:application/hal+json,我做了以下更改:

application/vnd.api+json

现在,在我从客户端应用程序发出请求后,我得到了spring.data.rest.defaultMediaType=application/vnd.api+json 的请求和响应。

但是..现在,当我尝试直接或通过邮递员访问API:ContentType时,应用程序进入无限循环,并在一段时间后发生堆栈溢出。

我使用杰克逊的注释尝试了一些解决方法,例如localhost:8080/api/users/1等,但这并没有帮助。

最让我困惑的是这个类与其他类/实体没有关系,所以可能导致这个循环的原因是什么?

编辑:

@JsonIgnoreProperties

1 个答案:

答案 0 :(得分:1)

Spring Data REST现在仅支持以下媒体类型:

  • application / hal + json
  • 应用/ JSON

https://docs.spring.io/spring-data/rest/docs/current/reference/html/#repository-resources.item-resource

但您可以在application/vnd.api+json支持的媒体类型中添加HAL JacksonHttpMessageConverter

您可以通过扩展WebMvcConfigurerAdapter类并覆盖extendMessageConverters方法来自定义邮件转换器:

package com.example;

import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    private static final MediaType APPLICATION_VND_API_JSON = MediaType.valueOf("application/vnd.api+json");
    private static final String HAL_JSON_SUBTYPE = "hal+json";

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.stream()
                .filter(TypeConstrainedMappingJackson2HttpMessageConverter.class::isInstance)
                .map(TypeConstrainedMappingJackson2HttpMessageConverter.class::cast)
                .filter(this::isHalConverter)
                .forEach(this::addVndApiMediaType);
        super.extendMessageConverters(converters);
    }

    private boolean isHalConverter(TypeConstrainedMappingJackson2HttpMessageConverter converter) {
        return converter.getSupportedMediaTypes().stream().anyMatch(type -> type.getSubtype().equals(HAL_JSON_SUBTYPE));
    }

    private void addVndApiMediaType(TypeConstrainedMappingJackson2HttpMessageConverter converter) {
        List<MediaType> supportedMediaTypes = new ArrayList<>(converter.getSupportedMediaTypes());
        supportedMediaTypes.add(APPLICATION_VND_API_JSON);
        converter.setSupportedMediaTypes(supportedMediaTypes);
    }
}

它仍然需要application.properties中的参数:

spring.data.rest.defaultMediaType=application/vnd.api+json

不幸的是,application/hal+json之后的请求在此次黑客攻击后无效。