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

Jackson反序列化异常:UnrecognizedPropertyException问题求助

解决Jackson反序列化UnrecognizedPropertyException的问题

看起来你遇到了一个典型的JSON结构与反序列化目标类不匹配的问题:从堆栈跟踪里的JSON片段能看出,你的接口响应是一个外层包含message、code、traceId等元数据的对象,真正的Country列表嵌套在data字段里,但你直接把整个JSON字符串反序列化成了Country类,这就导致Jackson试图把外层的message字段映射到Country类上,自然会抛出未识别字段的异常。

下面给你两种可行的解决方案:

方案1:创建匹配外层结构的响应类(推荐)

最规范的做法是创建一个外层响应类,完整匹配整个JSON的结构,再通过这个类获取内部的Country列表:

import java.util.List;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.*;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class CountryResponse {
    @JsonProperty("message")
    private String message;
    @JsonProperty("code")
    private String code;
    @JsonProperty("traceId")
    private String traceId;
    @JsonProperty("origin")
    private String origin;
    @JsonProperty("details")
    private String details;
    @JsonProperty("timestamp")
    private String timestamp;
    @JsonProperty("data")
    private Data data;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<>();

    // 所有字段的Getter和Setter方法
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public String getCode() { return code; }
    public void setCode(String code) { this.code = code; }
    public String getTraceId() { return traceId; }
    public void setTraceId(String traceId) { this.traceId = traceId; }
    public String getOrigin() { return origin; }
    public void setOrigin(String origin) { this.origin = origin; }
    public String getDetails() { return details; }
    public void setDetails(String details) { this.details = details; }
    public String getTimestamp() { return timestamp; }
    public void setTimestamp(String timestamp) { this.timestamp = timestamp; }
    public Data getData() { return data; }
    public void setData(Data data) { this.data = data; }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        additionalProperties.put(name, value);
    }

    // 内部类,用于映射data字段的结构
    public static class Data {
        @JsonProperty("countries")
        private List<Country> countries;
        @JsonIgnore
        private Map<String, Object> additionalProperties = new HashMap<>();

        public List<Country> getCountries() { return countries; }
        public void setCountries(List<Country> countries) { this.countries = countries; }

        @JsonAnyGetter
        public Map<String, Object> getAdditionalProperties() {
            return additionalProperties;
        }

        @JsonAnySetter
        public void setAdditionalProperty(String name, Object value) {
            additionalProperties.put(name, value);
        }
    }
}

然后修改反序列化代码,把目标类型改成CountryResponse:

ObjectMapper objectMapper = new ObjectMapper();
// 假设jsonString是你的响应JSON字符串
CountryResponse response = objectMapper.readValue(jsonString, CountryResponse.class);
// 获取Country列表
List<Country> countries = response.getData().getCountries();

方案2:直接解析JSON树提取目标数据

如果不想创建额外的响应类,也可以通过Jackson的JSON树API直接提取data里的countries部分再反序列化:

ObjectMapper objectMapper = new ObjectMapper();
// 先把JSON解析成树结构
JsonNode rootNode = objectMapper.readTree(jsonString);
// 定位到countries节点
JsonNode countriesNode = rootNode.path("data").path("countries");
// 把节点反序列化成Country列表
List<Country> countries = objectMapper.readValue(
    countriesNode.traverse(), 
    new com.fasterxml.jackson.core.type.TypeReference<List<Country>>(){}
);

额外提示:不要盲目关闭未知字段检查

有些同学会想到通过配置ObjectMapper来忽略未知字段:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

但这只是绕过错误,不是解决根本问题——因为你本来就不该把外层JSON映射到Country类,这种做法会隐藏结构不匹配的潜在问题,不推荐使用。

内容的提问来源于stack exchange,提问作者Randika Ratnayake

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:52:45