Spring Boot通过自定义属性序列化Kotlin Enum

发布于 2025-02-09 08:03:43 字数 1815 浏览 1 评论 0原文

我有一个枚举,我想使用自定义属性序列化。它在我的测试中起作用,但在我提出请求时不起作用。

应在测试中使用JSONVALUE映射枚举,

enum class PlantProtectionSortColumn(
    @get:JsonValue val propertyName: String,
) {

    NAME("name"),
    REGISTRATION_NUMBER("registrationNumber");

}

按预期,小写案例的作用。


class PlantProtectionSortColumnTest : ServiceSpec() {

    @Autowired
    lateinit var mapper: ObjectMapper

    data class PlantProtectionSortColumnWrapper(
        val sort: PlantProtectionSortColumn,
    )

    init {
        // this works
        test("Deserialize PlantProtectionSortColumn enum with custom name ") {
            val json = """
                {
                    "sort": "registrationNumber"
                }
            """
            val result = mapper.readValue(json, PlantProtectionSortColumnWrapper::class.java)
            result.sort shouldBe PlantProtectionSortColumn.REGISTRATION_NUMBER
        }

        // this one fails
        test("Deserialize PlantProtectionSortColumn enum with enum name ") {
            val json = """
                {
                    "sort": "REGISTRATION_NUMBER"
                }
            """
            val result = mapper.readValue(json, PlantProtectionSortColumnWrapper::class.java)
            result.sort shouldBe PlantProtectionSortColumn.REGISTRATION_NUMBER
        }
    }
}


但是在控制器中,当我用小写发送请求时,我会得到400。但是,当请求与枚举名称相匹配时,它可以正常工作,但是响应将返回小写。因此,Spring不仅不仅对objectMapper进行请求,因此使用它。

private const val RESOURCE_PATH = "$API_PATH/plant-protection"


@RestController
@RequestMapping(RESOURCE_PATH, produces = [MediaType.APPLICATION_JSON_VALUE])
class PlantProtectionController() {

    @GetMapping("/test")
    fun get(
        @RequestParam sortColumn: PlantProtectionSortColumn,
    ) = sortColumn

}

I have an Enum and I would like to serialize it using custom property. It works in my tests but not when I make request.

Enum should be mapped using JsonValue

enum class PlantProtectionSortColumn(
    @get:JsonValue val propertyName: String,
) {

    NAME("name"),
    REGISTRATION_NUMBER("registrationNumber");

}

In test the lowercase case works as expected.


class PlantProtectionSortColumnTest : ServiceSpec() {

    @Autowired
    lateinit var mapper: ObjectMapper

    data class PlantProtectionSortColumnWrapper(
        val sort: PlantProtectionSortColumn,
    )

    init {
        // this works
        test("Deserialize PlantProtectionSortColumn enum with custom name ") {
            val json = """
                {
                    "sort": "registrationNumber"
                }
            """
            val result = mapper.readValue(json, PlantProtectionSortColumnWrapper::class.java)
            result.sort shouldBe PlantProtectionSortColumn.REGISTRATION_NUMBER
        }

        // this one fails
        test("Deserialize PlantProtectionSortColumn enum with enum name ") {
            val json = """
                {
                    "sort": "REGISTRATION_NUMBER"
                }
            """
            val result = mapper.readValue(json, PlantProtectionSortColumnWrapper::class.java)
            result.sort shouldBe PlantProtectionSortColumn.REGISTRATION_NUMBER
        }
    }
}


But in controller, when i send request with lowercase I get 400. But when the request matches the enum name It works, but response is returned with lowercase. So Spring is not using the objectMapper only for request, in response it is used.

private const val RESOURCE_PATH = "$API_PATH/plant-protection"


@RestController
@RequestMapping(RESOURCE_PATH, produces = [MediaType.APPLICATION_JSON_VALUE])
class PlantProtectionController() {

    @GetMapping("/test")
    fun get(
        @RequestParam sortColumn: PlantProtectionSortColumn,
    ) = sortColumn

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨与橙与城 2025-02-16 08:03:43

我相信KQR的答案是正确的,您需要配置转换器,而不是JSON DESERIALISER。

看起来像:

    @Component
    class StringToPlantProtectionSortColumnConverter : Converter<String, PlantProtectionSortColumn> {

    override fun convert(source: String): PlantProtectionSortColumn {
        return PlantProtectionSortColumn.values().firstOrNull { it.propertyName == source }
            ?: throw NotFoundException(PlantProtectionSortColumn::class, source)
    }}
    

I believe kqr's answer is correct and you need to configure converter, not JSON deserializer.

It could look like:

    @Component
    class StringToPlantProtectionSortColumnConverter : Converter<String, PlantProtectionSortColumn> {

    override fun convert(source: String): PlantProtectionSortColumn {
        return PlantProtectionSortColumn.values().firstOrNull { it.propertyName == source }
            ?: throw NotFoundException(PlantProtectionSortColumn::class, source)
    }}
    
等风来 2025-02-16 08:03:43

在您的端点中,您不是在解析JSON主体,而是查询参数,而不是JSON格式。

In your endpoint you are not parsing json body but query parameters, which are not in json format.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文