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

父子POJO结合@RequestBody使用异常:父类字段未被赋值

解决Spring Controller接收子类对象时父类字段未赋值的问题

在Spring项目中定义了父类CommonInfo和子类JavaDeveloper(继承自CommonInfo),通过Controller的@RequestBody接收子类对象时,传入包含父子类字段的JSON请求体,仅子类字段能被正确赋值,父类字段始终为空。

相关代码

父类CommonInfo

@JsonIgnoreProperties(ignoreUnknown = true)
public class CommonInfo {
    
    @NotNull(message = "name is mandatory")
    String name;
    
    @NotNull(message = "pan is mandatory")
    String pan;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPan() {
        return pan;
    }

    public void setPan(String pan) {
        this.pan = pan;
    }
}

子类JavaDeveloper

@JsonIgnoreProperties(ignoreUnknown = true)
public class JavaDeveloper extends CommonInfo{
    
    @NotNull(message = "currentPoject is mandatory")
    String currentPoject;
    
    @NotNull(message = "timeline is mandatory")
    String timeline;

    public String getCurrentPoject() {
        return currentPoject;
    }

    public void setCurrentPoject(String currentPoject) {
        this.currentPoject = currentPoject;
    }

    public String getTimeline() {
        return timeline;
    }

    public void setTimeline(String timeline) {
        this.timeline = timeline;
    }
}

Controller代码

@RequestMapping(value = "/createUser", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE)
public ResponsePacket createJavaDeveloper(@Valid @RequestBody JavaDeveloper requestPacket) {
     return new ResponsePacket();
}

JSON请求体

{
    "name" : "Smith",
    "pan" : "DFREW1243E",
    "currentPoject" : "Banking project",
    "timeline" : "13-04-2023"
}

问题原因

核心原因是Jackson在反序列化继承类时,无法识别父类中包私有访问权限的字段。虽然父类提供了public的getter和setter方法,但Jackson默认的字段访问策略会优先尝试直接访问字段,而包私有字段只能被同一包内的类访问,若子类与父类不在同一包下,Jackson就无法直接读写这些字段,导致父类字段无法被赋值。

解决方案

方案一:给父类字段添加@JsonProperty注解

通过@JsonProperty注解明确指定字段对应的JSON键名,强制Jackson通过getter/setter方法处理字段,而非直接访问字段本身。修改后的父类代码如下:

@JsonIgnoreProperties(ignoreUnknown = true)
public class CommonInfo {
    
    @JsonProperty
    @NotNull(message = "name is mandatory")
    String name;
    
    @JsonProperty
    @NotNull(message = "pan is mandatory")
    String pan;

    // getter和setter方法保持不变
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPan() {
        return pan;
    }

    public void setPan(String pan) {
        this.pan = pan;
    }
}

方案二:修改父类字段的访问权限为public

将父类的name和pan字段改为public访问权限,让Jackson可以直接访问这些字段:

@JsonIgnoreProperties(ignoreUnknown = true)
public class CommonInfo {
    
    @NotNull(message = "name is mandatory")
    public String name;
    
    @NotNull(message = "pan is mandatory")
    public String pan;

    // getter和setter方法可保留或移除,视需求而定
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPan() {
        return pan;
    }

    public void setPan(String pan) {
        this.pan = pan;
    }
}

方案三:全局配置Jackson的字段访问策略

通过Spring配置类全局设置Jackson的字段访问策略,使其优先使用setter方法进行反序列化:

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 设置字段访问策略为仅通过getter/setter方法访问
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.NONE);
        objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.PUBLIC_ONLY);
        objectMapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.PUBLIC_ONLY);
        return objectMapper;
    }
}

内容的提问来源于stack exchange,提问作者Intekhab Alam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:52:05