简体   繁体   English

如何在不知道子类的情况下通过实现的接口反序列化枚举

[英]How to deserialize enum by implemented interface without knowing sub-classes

I am writing a custom spring boot starter that provides a uniform error response class for all repositories that will add this starter.我正在编写一个自定义的 spring 引导启动程序,它为将添加此启动程序的所有存储库提供统一的错误响应 class。 It also provides the corresponding exception handler.它还提供了相应的异常处理程序。 The problem is, that this error response needs an error code which might differ between all those repositories, using my starter.问题是,这个错误响应需要一个错误代码,它可能在所有这些存储库之间不同,使用我的启动器。 So the solution would be to create an error response with an error code that is an interface.所以解决方案是创建一个错误响应,错误代码是一个接口。 Other repositories can then create enums implementing this interface to achieve the desired behavior.然后其他存储库可以创建实现此接口的枚举以实现所需的行为。 It is written in kotlin写在kotlin

interface BaseErrorCode {
    val message: String
}

class ErrorResponse {
    val customMessage: String,
    val errorCode: BaseErrorCode,
    val timestamp: OffsetDateTime
}

Now, in another repository, I use this starter, get access to the classes above and create my error code enum:现在,在另一个存储库中,我使用这个启动器,访问上面的类并创建我的错误代码枚举:

enum class MyCustomErrorCodes : BaseErrorCode {
    FOO
}

Now, I can throw an exception and through the handler, this json will be produced:现在,我可以抛出异常并通过处理程序生成这个 json:

{
    "customMessage": "My message",
    "errorCode": "FOO",
    "timestamp": "2023-01-27T12:15:31.7730645+01:00"
}

So serializing works absolutely fine.所以序列化工作绝对没问题。

However, when deserializing the ErrorResponse in my integration-tests, I get the following exception:但是,在我的集成测试中反序列化ErrorResponse时,出现以下异常:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `my.package.BaseErrorCode` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{"customMessage":"My message","errorCode":"FOO","timestamp":"2023-01-27T12:12:06.4932227+01:00"}"; line: 1, column: 54] (through reference chain: my.package.ErrorResponse["errorCode"])

Approach 1 I know a solution where you write a custom deserializer.方法 1我知道一个解决方案,您可以在其中编写自定义解串器。 But this could not be placed in the spring boot starter because I need to know the implementing classes of that ´BaseErrorCode`-interface.但这不能放在 spring 引导启动器中,因为我需要知道该“BaseErrorCode”接口的实现类。

Approach 2 Using @JsonSubType , I can also tell Jackson how to handle this interface.方法 2使用@JsonSubType ,我还可以告诉 Jackson 如何处理这个接口。 But I do need some information about implementing enums as well, which I do not have in my starter但是我也确实需要一些关于实现枚举的信息,我的启动器中没有这些信息

Is there any way to deserialize this error response有没有办法反序列化这个错误响应

  • only by modifying the starter, not each repository仅通过修改启动器,而不是每个存储库
  • without knowing the classes that implement BaseErrorCode , BUT knowing that it will ALWAYS be an enum?不知道实现BaseErrorCode的类,但知道它总是一个枚举?

I think the answer lies in using intentionally dissimilar objects.我认为答案在于有意使用不同的对象。 I have not tested, but I think:我没有测试过,但我认为:

  • follow what you have with serialization, and note that you are not serializing the whole enum rather an instance of enum which conforms to BaseErrorCode .遵循序列化的内容,并注意您不是序列化整个enum ,而是序列化符合BaseErrorCodeenum实例
  • on deserialization you make a concrete implementation of BaseErrorCode (this can be private to the Starter) that you deserialize the JSON in to.在反序列化中,您对BaseErrorCode (这对于 Starter 来说是私有的)进行了具体实现,您将 JSON 反序列化到其中。 (Adding @JsonIgnoreProperties(ignoreUnknown = true) to guard against an unknown subclass sending more data than you can deal with). (添加@JsonIgnoreProperties(ignoreUnknown = true)以防止未知子类发送超出您处理能力的数据)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Kotlin ENUM类具有由代理实现的通用接口 - Kotlin ENUM classes with common interface implemented by delegates 如何在春季反序列化WWW表单字段枚举? - How to deserialize WWW form field to enum in Spring? 如何使用Gson反序列化继承的Kotlin数据类 - How to deserialize inherited Kotlin data classes with Gson 您如何摆脱多余的强制转换到已实现的接口? - How do you get rid of superfluous casts to implemented interface? 如何在枚举类中使用不同类型的占位符 - How to use different kinds of placeholders in enum classes 如何使IntelliJ IDEA突出显示接口的已实现方法 - How to make IntelliJ IDEA highlight the implemented methods of an interface 在内部的Splashscreen Activity中,我实现了该界面。 如何在Kotlin中向多个Activity发送接口数据? - In Splashscreen Activity inside I implemented the interface. How to send data of interface to multiple Activity in Kotlin? 如何在不知道类型的情况下从泛型函数调用函数? - How to call function from generic function without knowing the type? 如何将子类“加入”到超类型实例中? - How to "join" sub classes into a super type instance? 如何知道两个类是否实现一个公共接口? - How to know if two classes implement a common interface?
 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM