在@OneToMany Set< Object>上使用@JsonSerialize(using = MySerializer.class). [英] Use @JsonSerialize(using=MySerializer.class) on a @OneToMany Set<Object>

查看:233
本文介绍了在@OneToMany Set< Object>上使用@JsonSerialize(using = MySerializer.class).的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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时,我遇到了一个非常相似的问题.添加带有usingkeyUsing的自定义序列化程序都可以正常工作,但是带有@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&lt; Object&gt;上使用@JsonSerialize(using = MySerializer.class).的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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