为什么在使用 Spring HATEOAS Jackson 序列化程序时会收到警告
Why do I get warnings when using Spring HATEOAS Jackson serializers
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 将序列化程序绑定到如下类型:
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
进行序列化和反序列化。但是,执行seems limited in its ability to embed resources。在尝试解决此限制时,我尝试使用上述 Jackson mixin 中的注释在我自己的 class:
中使用 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
} ]
}
}
那么为什么会出现警告,为什么尽管有警告它仍然有效? module and serializer are public。
当您使用 @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
时,Jackson 会尝试创建 Jackson2HalModule.HalResourcesSerializer
的实例,但该实例不起作用,因为它没有默认构造函数。
Spring HATEOAS(稍后)直接 注册一些 Jackson 的东西,包括 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 将序列化程序绑定到如下类型:
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
进行序列化和反序列化。但是,执行seems limited in its ability to embed resources。在尝试解决此限制时,我尝试使用上述 Jackson mixin 中的注释在我自己的 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;
}
}
这有效,但会导致以下 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
} ]
}
}
那么为什么会出现警告,为什么尽管有警告它仍然有效? module and serializer are public。
当您使用 @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class)
时,Jackson 会尝试创建 Jackson2HalModule.HalResourcesSerializer
的实例,但该实例不起作用,因为它没有默认构造函数。
Spring HATEOAS(稍后)直接 注册一些 Jackson 的东西,包括 Jackson2HalModule.HalResourcesSerializer
。现在序列化按预期工作,因为序列化程序的实例已成功注册。