在@OneToMany Set< Object>上使用@JsonSerialize(using = MySerializer.class). [英] Use @JsonSerialize(using=MySerializer.class) on a @OneToMany Set<Object>
问题描述
在Spring Boot/Spring Data Rest项目中,我在@OneToMany属性上使用自定义JsonSerializer<Set<Object>>
时遇到问题.当我执行HTTP GET/collection请求时,出现以下错误:
In a Spring Boot/Spring Data Rest project i have issues to use a custom JsonSerializer<Set<Object>>
on a @OneToMany property. When i do an HTTP GET /collection request i have the following error:
无法写入HTTP消息: org.springframework.http.converter.HttpMessageNotWritableException: 无法写入内容:无法覆盖序列化程序(通过 参考链: org.springframework.hateoas.Resources ["_ embedded"]-> java.util.UnmodifiableMap ["analogParameters"]-> java.util.ArrayList [0]); 嵌套的例外是 com.fasterxml.jackson.databind.JsonMappingException:无法覆盖 序列化器(通过参考链: org.springframework.hateoas.Resources ["_ embedded"]-> java.util.UnmodifiableMap ["analogParameters"]-> java.util.ArrayList [0])
Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Can not override serializer (through reference chain: org.springframework.hateoas.Resources["_embedded"]->java.util.UnmodifiableMap["analogParameters"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not override serializer (through reference chain: org.springframework.hateoas.Resources["_embedded"]->java.util.UnmodifiableMap["analogParameters"]->java.util.ArrayList[0])
以下是我的实体类的摘录:
Below is an extract of my entity class:
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="output_parameter_id")
@JsonSerialize(using=InputParametersSerializer.class)
//@Transcient
private Set<InputParameter> inputParameters = new HashSet<InputParameter>();
public Set<InputParameter> getInputParameters() {
return inputParameters;
}
public void setInputParameters(Set<InputParameter> inputParameters) {
this.inputParameters = inputParameters;
}
和JsonSerializer<Set<InputParameter>>
public class InputParametersSerializer
extends JsonSerializer<Set<InputParameter>> {
static final long serialVersionUID = 123L;
public void serialize (Set<InputParameter> ips, JsonGenerator jg,
SerializerProvider sp)
throws IOException {
jg.writeString("Yeah");
}
}
如果我删除@OneToMany并将该属性定义为@transient,它将按预期工作.
If i remove @OneToMany and define the property as @transient it works as expected.
InputParameter实体没有关联的存储库(不会导出为其余资源).
InputParameter entity has no Repository associated (it is not exported as a rest resource).
如何在@OneToMany属性上利用JsonSerializer?
How can a make use of a JsonSerializer on a @OneToMany property?
推荐答案
在使用Spring Boot 2.1.0时,我遇到了一个非常相似的问题.添加带有using
和keyUsing
的自定义序列化程序都可以正常工作,但是带有@OneToMany
带注释字段的自定义反序列化器会抛出与您得到的相同的JsonMappingException: Can not override serializer
消息,而带有@ElementCollection
的序列化器则很简单忽略了.我怀疑Spring Data Rest会做一些未记录的魔术,以解决这些字段的(反序列化)问题,这些字段在添加自定义反序列化器后效果不佳.我的解决方法是通过带注释的getter和setter添加额外的JSON字段.以您的示例为例,
I ran into a very similar issue while using Spring Boot 2.1.0. Adding a custom serializer, both with using
and keyUsing
, works fine, but a custom deserializer with a @OneToMany
annotated field throws out the same JsonMappingException: Can not override serializer
message you got, while with an @ElementCollection
it just plain gets ignored. I suspect Spring Data Rest does some undocumented magic in order to take care of the (de)serialization of these kinds of fields that does not play nice with the addition of a custom deserializer. My workaround to this was adding an extra JSON field through an annotated getter and setter. With your example, it would look like:
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="output_parameter_id")
private Set<InputParameter> inputParameters = new HashSet<InputParameter>();
public Set<InputParameter> getInputParameters() {
return inputParameters;
}
public void setInputParameters(Set<InputParameter> inputParameters) {
this.inputParameters = inputParameters;
}
@JsonSerialize(using=InputParametersSerializer.class)
public Set<InputParameter> getInputParametersSet() {
return getInputParameters();
}
@JsonDeserialize(using=InputParametersDeserializer.class)
public void setInputParametersSet(Set<InputParameter> inputParameters) {
setInputParameters(inputParameters);
}
哪个会输出类似
{
...
"inputParameters" : ...,
"inputParametersSet" : ...,
...
}
尽管不理想,但该字段的序列化和反序列化仍按预期进行.
或者,为了保留字段名称,对@ElementCollection
使用了类似的解决方法,但对@OneToMany
使用了不:
While not ideal, serialization and deserialization of this field works as expected.
alternatively, in order to keep the field name, a similar workaround worked with @ElementCollection
but not with @OneToMany
:
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="output_parameter_id")
@JsonIgnore
private Set<InputParameter> inputParameters = new HashSet<InputParameter>();
public Set<InputParameter> getInputParameters() {
return inputParameters;
}
public void setInputParameters(Set<InputParameter> inputParameters) {
this.inputParameters = inputParameters;
}
@JsonProperty("inputParameters")
@JsonSerialize(using=InputParametersSerializer.class)
public Set<InputParameter> getInputParametersSet() {
return getInputParameters();
}
@JsonProperty("inputParameters")
@JsonDeserialize(using=InputParametersDeserializer.class)
public void setInputParametersSet(Set<InputParameter> inputParameters) {
setInputParameters(inputParameters);
}
最后,我不得不采用第一种方法.
In the end I had to go with the first approach.
这篇关于在@OneToMany Set< Object>上使用@JsonSerialize(using = MySerializer.class).的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!