在 spring 中使用枚举反序列化抽象类

问题描述 投票:0回答:1

假设我们有一个类

InstantMessage
,它有一个抽象子类
IMContent content

public class InstantMessage {
    // other fields
    private MessageType type;
    private IMContent content;
}

public enum MessageType {
    TEXT, IMAGE, VIDEO, PRODUCT, SHOPPING_ORDER, SYSTEM;
}

public abstract class IMContent {
    public abstract String toText();
}

IMContent
有很多实现,比如
IMTextContent
IMImageContent
,这取决于消息的类型。

当在

InstantMessage
@RequestBody
中使用
@RequestPart
时,Spring无法反序列化
IMContent

我尝试了几种方法,但它们都有一些明显的缺陷。

首先,我尝试将

@JsonDeserialize(using = IMContentDeserialzer.class)
添加到
content
中,但这需要我手动反序列化除内容之外的其他字段,这在添加另一个字段时非常不方便且容易忘记。我可以接受手动编写
IMContent
的反序列化,但不是整个
InstantMessage
。我希望有一种简单的方法来反序列化“非内容”字段。

我的第二次尝试是使用

@JsonTypeInfo
@JsonSubTypes
,但这似乎需要我将
type
InstantMessage
移动到
IMContent
。当我需要直接从
type
访问
InstantMessage
或者直接访问文本内容时也很不方便。例如,如果我需要搜索文本内容,我需要将内容展平为数据库中的字符串,当我从数据库中获取
InstantMessage
时,我需要再次类似于内容。

我也有一些解决方法,比如使用

Map
而不是
IMContent
,或者动态地将内容反序列化为
IMContent
,或者使
InstantMessage
抽象,但我认为它们并不优雅。

在这种情况下解决这个问题最简单的方法是什么?

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type",
        visible = true
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = IMTextContent.class, name = "TEXT"),
        @JsonSubTypes.Type(value = IMImageContent.class, name = "IMAGE"),
        @JsonSubTypes.Type(value = IMProductContent.class, name = "PRODUCT"),
        @JsonSubTypes.Type(value = IMShoppingOrderContent.class, name = "SHOPPING_ORDER"),
})
public abstract class IMContent {

    public abstract String toText();

}
java spring
1个回答
0
投票

您是否考虑过创建自定义 Spring converter。这是一个草稿示例。

@Component
public class IMContentConverter implements Converter<String, IMContent> { //Now the endpoint should receive IMContent as body instead of InstantMessage
  @Autowired
  private ObjectMapper objectMapper;
    public IMContent convert(String source) {
        return objectMapper.readValue(source, IMContent.class);
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.