为什么在使用Spring HATEOAS Jackson序列化器时收到警告 [英] Why do I get warnings when using Spring HATEOAS Jackson serializers

查看:117
本文介绍了为什么在使用Spring HATEOAS Jackson序列化器时收到警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Spring HATEOAS 定义 Jackson mixins 将序列化程序绑定到如下类型:

package org.springframework.hateoas.hal;

// Imports omitted

public abstract class ResourcesMixin<T> extends Resources<T> {

    @Override
    @XmlElement(name = "embedded")
    @JsonProperty("_embedded")
    @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = Jackson2HalModule.HalResourcesSerializer.class)
    @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
    public abstract Collection<T> getContent();    
}

此mixin导致扩展Resources<T>的类型使用Jackson2HalModule.HalResourcesSerializer.class进行序列化和反序列化.但是,实现似乎在嵌入资源的能力方面受到限制.在尝试解决此限制时,我尝试使用上述Jackson混合中的注释在我自己的类中使用Spring HATEOAS序列化器:

package mypackage;

// Imports omitted

public class ModelAResource extends Resource<ModelA> {

    private Collection<Resource<ModelB>> modelBResources;

    public ModelAResource(Model model, Collection<Resource<ModelB>> modelBResources) {
        super(model);
        this.modelBResources = modelBResources;
    }

    @JsonProperty("_embedded")
    @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = Jackson2HalModule.HalResourcesSerializer.class)
    @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
    public Collection<Resource<ModelB>> getModelBResources() {
        return modelBResources;
    }
}

这可行,但是导致以下WARN记录:

[2015-01-27 23:36:41.469] boot - 12516  WARN [qtp1175418534-17] ---
MappingJackson2HttpMessageConverter: Failed to evaluate serialization for type
[class mypackage.ModelAResource]:
org.springframework.beans.factory.BeanCreationException: Error creating bean 
with name
'org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer':
Instantiation of bean failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate
[org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer]: No
default constructor found; nested exception is
java.lang.NoSuchMethodException:
org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer<init>()

[2015-01-27 23:36:41.478] boot - 12516  WARN [qtp1175418534-17] ---
MappingJackson2HttpMessageConverter: Failed to evaluate serialization for type
[class mypackage.ModelAResource]:
com.fasterxml.jackson.databind.JsonMappingException: Class
org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer has no 
default (no arg) constructor 

尽管有这些警告,序列化仍会产生预期的期望结果:

{
  "id" : 6,
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/modelA/6"
    },
    "links" : {
      "href" : "http://localhost:8080/modelA/6/modelBs"
    }
  },
  "_embedded" : {
    "modelBs" : [ {
      "_links": {
        "self": {
          "href": "http://localhost:8080/modelA/6/modelBs/1"
        }
      }, 
      "id" : 1
    } ]
  }
}

那么为什么要发出警告,为什么在发出警告的情况下仍然可以起作用? 解决方案

使用@JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)时,Jackson尝试创建Jackson2HalModule.HalResourcesSerializer的实例,该实例不起作用,因为它没有默认构造函数.

Spring HATEOAS(后来)直接 注册了杰克逊的一些东西,包括Jackson2HalModule.HalResourcesSerializer.现在,序列化可以按预期工作,因为已成功注册了序列化器的实例.

Spring HATEOAS defines and registers a HttpMessageConverter with a Jackson module that contains serializers to transform its ResourceSupport and Resources types to HAL JSON representations. The modules uses Jackson mixins to bind the serializers to types like so:

package org.springframework.hateoas.hal;

// Imports omitted

public abstract class ResourcesMixin<T> extends Resources<T> {

    @Override
    @XmlElement(name = "embedded")
    @JsonProperty("_embedded")
    @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = Jackson2HalModule.HalResourcesSerializer.class)
    @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
    public abstract Collection<T> getContent();    
}

This mixin causes types that extend Resources<T> to get serialized and deserialized using Jackson2HalModule.HalResourcesSerializer.class. However, the implementation seems limited in its ability to embed resources. In trying to address this limitation, I tried using annotations from the above Jackson mixin to use the Spring HATEOAS serializers in my own class:

package mypackage;

// Imports omitted

public class ModelAResource extends Resource<ModelA> {

    private Collection<Resource<ModelB>> modelBResources;

    public ModelAResource(Model model, Collection<Resource<ModelB>> modelBResources) {
        super(model);
        this.modelBResources = modelBResources;
    }

    @JsonProperty("_embedded")
    @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = Jackson2HalModule.HalResourcesSerializer.class)
    @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
    public Collection<Resource<ModelB>> getModelBResources() {
        return modelBResources;
    }
}

This works, but leads to the following WARNs getting logged:

[2015-01-27 23:36:41.469] boot - 12516  WARN [qtp1175418534-17] ---
MappingJackson2HttpMessageConverter: Failed to evaluate serialization for type
[class mypackage.ModelAResource]:
org.springframework.beans.factory.BeanCreationException: Error creating bean 
with name
'org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer':
Instantiation of bean failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate
[org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer]: No
default constructor found; nested exception is
java.lang.NoSuchMethodException:
org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer<init>()

[2015-01-27 23:36:41.478] boot - 12516  WARN [qtp1175418534-17] ---
MappingJackson2HttpMessageConverter: Failed to evaluate serialization for type
[class mypackage.ModelAResource]:
com.fasterxml.jackson.databind.JsonMappingException: Class
org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer has no 
default (no arg) constructor 

Despite these warnings, serialization yields the expected, desired result:

{
  "id" : 6,
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/modelA/6"
    },
    "links" : {
      "href" : "http://localhost:8080/modelA/6/modelBs"
    }
  },
  "_embedded" : {
    "modelBs" : [ {
      "_links": {
        "self": {
          "href": "http://localhost:8080/modelA/6/modelBs/1"
        }
      }, 
      "id" : 1
    } ]
  }
}

So why the warnings, and why does it work despite the warnings? The module and serializer are public.

解决方案

When you use @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class), then Jackson tries to create an instance of Jackson2HalModule.HalResourcesSerializer, which doesn't work because it has no default constructor.

Spring HATEOAS (later) directly registers some Jackson stuff, including a Jackson2HalModule.HalResourcesSerializer. Now serialization works as expected because an instance of the serializer has successfully been registered.

这篇关于为什么在使用Spring HATEOAS Jackson序列化器时收到警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆