You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过注解为FeignClient特定响应解包根元素?

问题描述

我有一个调用外部服务的FeignClient,代码如下:

interface JiraClient {
    // ...

    @RequestMapping(method = [RequestMethod.GET], value = ["\${jira.api.agile}/sprint/{sprintId}/issue"])
    fun getIssuesForASprint(
        @PathVariable("sprintId") sprintId: Int,
        @RequestParam(name = "startAt", required = false) startAt: Int = 0,
        @RequestParam(name = "maxResults", required = false) maxResults: Int = MAX_RESULTS
    ): IssueHolder

    @RequestMapping(method = [RequestMethod.GET], value = ["\${jira.api.insight}/objectschema/list"])
    fun getObjectSchemaList(): List<ObjectSchema>
}

对应的ObjectSchema数据类代码:

@JsonIgnoreProperties(ignoreUnknown = true)
data class ObjectSchema(
    @JsonProperty("id") val id: Int,
    @JsonProperty("name") val name: String?,
    @JsonProperty("objectSchemaKey") val objectSchemaKey: String?,
    @JsonProperty("status") val status: String?,
    @JsonProperty("created") @JsonFormat(
        shape = JsonFormat.Shape.STRING,
        pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    ) val created: Date?,
    @JsonProperty("updated") @JsonFormat(
        shape = JsonFormat.Shape.STRING,
        pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    ) val updated: Date?,
    @JsonProperty("objectCount") val objectCount: Int?,
    @JsonProperty("objectTypeCount") val objectTypeCount: Int?
)

这个接口无法正常工作,因为外部服务返回的响应包含额外的根元素:

{
    "objectschemas": [
        {
            "id": 1,
            "name": "APPS CATALOG",
            "objectSchemaKey": "AC",
            "status": "Ok",
            "created": "2020-01-01T11:11:11.000Z",
            "updated": "2020-01-01T11:11:11.000Z",
            "objectCount": 123,
            "objectTypeCount": 10
        },
        {
            "id": 2,
            "name": "ORG CATALOG",
            "objectSchemaKey": "OC",
            "status": "Ok",
            "created": "2020-01-01T11:11:11.000Z",
            "updated": "2020-01-01T11:11:11.000Z",
            "objectCount": 456,
            "objectTypeCount": 20
        }
    ]
}

对于其他带分页信息的响应,我已经用Holder数据类处理(比如IssueHolder对应包含issues数组的分页响应),但这次希望通过给特定数据类加注解的简单方式,实现根元素objectschemas的解包。这个数据类只用来反序列化,不需要序列化,而且不想在自定义Feign Decoder里加大量逻辑,也没法在FeignClient接口里配置DeserializationFeature.UNWRAP_ROOT_VALUE,想问下最简单的实现方法是什么?

解决方案

最省事的方式是创建一个仅用于反序列化的Holder数据类,用Jackson注解匹配根元素,原有ObjectSchema类完全不用改:

  1. 新增ObjectSchemaHolder类:
@JsonRootName("objectschemas")
@JsonIgnoreProperties(ignoreUnknown = true)
data class ObjectSchemaHolder(
    @JsonValue val schemas: List<ObjectSchema>
)
  • @JsonRootName指定要匹配的根元素名objectschemas
  • @JsonValue表示这个类的实例直接对应根元素的数组内容,反序列化时会自动把根元素里的数组映射到schemas字段
  1. 修改FeignClient接口的返回类型:
@RequestMapping(method = [RequestMethod.GET], value = ["\${jira.api.insight}/objectschema/list"])
fun getObjectSchemaList(): ObjectSchemaHolder
  1. 调用接口时直接取holder.schemas就能拿到目标列表。

如果不想改接口返回类型,也可以给接口方法的返回值加@JsonDeserialize指定自定义解包器,但这种写法不如Holder类直观,代码量也更多。上面的Holder类方案完全符合你的要求:只用注解实现解包,不用改全局Decoder配置,代码少,而且只服务于反序列化场景。

内容的提问来源于stack exchange,提问作者Jing Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:27:24