java - 在 @OneToMany Set<Object> 上使用 @JsonSerialize(using=MySerializer.class)

标签 java hibernate jackson spring-data-rest

在 Spring Boot/Spring Data Rest 项目中,我在使用自定义 JsonSerializer<Set<Object>> 时遇到问题在 @OneToMany 属性上。当我执行 HTTP GET/collection 请求时,出现以下错误:

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])

下面是我的实体类的摘录:

@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,它将按预期工作。

InputParameter 实体没有关联的 Repository(它不作为 rest 资源导出)。

如何在@OneToMany 属性上使用 JsonSerializer?

最佳答案

我在使用 Spring Boot 2.1.0 时遇到了一个非常相似的问题。添加自定义序列化器,同时使用 usingkeyUsing,工作正常,但是带有 @OneToMany 注释字段的自定义反序列化器抛出相同的 JsonMappingException: Can not override serializer 消息,而使用 @ElementCollection 它只是简单地被忽略。我怀疑 Spring Data Rest 做了一些未记录的魔术,以便处理这些类型的字段的(反)序列化,这些字段在添加自定义反序列化器时效果不佳。我的解决方法是通过带注释的 getter 和 setter 添加一个额外的 JSON 字段。对于您的示例,它看起来像:

@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:

@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);
}

最后我不得不采用第一种方法。

关于java - 在 @OneToMany Set<Object> 上使用 @JsonSerialize(using=MySerializer.class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40490867/

相关文章:

java - 将列表序列化为 JSON 数组

java - 转换为 JSON 后保留 XMLGregorianCalendar 日期格式 - Jackson Lib

java - 自定义异常(exception)或空列表

java - dom4j - xpath - 获取 xml 作为 Document.valueOf 的字符串

java - Hibernate 一对一映射表现为一对多

java - 如果使用双引号,则无法使用 Hibernate 插入行

java - Jackson - 如何基于 json 内容应用自定义反序列化?

java - Groovy 脚本性能包含与匹配

Java 接口(interface)/实现命名约定

java - 具有 transient 属性的 Hibernate SQLQuery