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

存在公共Setter时Jackson仍无法反序列化对象的原因

问题:Jackson反序列化JPA实体类失败,明明有Setter却需要String参数构造方法?

实体类定义

我定义了如下JPA实体类DummyEntity,包含公共无参构造方法及所有属性的Getter、Setter:

package com.example.demo.DummyObject;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.*;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * An entity containing analyzed data
 *
 * @author Thorvas
 */
@Entity
@Table(name="DUMMY_ENTITY")
public class DummyEntity {

    public DummyEntity() {

    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "name")
    private String name;

    @ElementCollection
    private Map<String, Integer> population;

    @Column(name = "estimation")
    private int estimation;

    @Column(name = "last_updated")
    @Temporal(TemporalType.DATE)
    @JsonFormat(pattern = "yyyy-MM-dd")
    @JsonProperty("last_updated")
    private Date lastUpdated;

    public String getName() {
        return name;
    }

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

    public Map<String, Integer> getPopulation() {
        return population;
    }

    public void setPopulation(Map<String, Integer> population) {
        this.population = population;
    }

    public int getEstimation() {
        return estimation;
    }

    public void setEstimation(int estimation) {
        this.estimation = estimation;
    }

    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setLastUpdated(Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

提交的请求JSON

向POST接口提交如下JSON数据:

{
  "name": "Powiat ząbkowicki",
  "population": {
    "2013": 67875,
    "2014": 67458,
    "2015": 66971,
    "2016": 66527,
    "2017": 66009,
    "2018": 65428,
    "2019": 64802,
    "2020": 62561,
    "2021": 61846,
    "2022": 61087
  },
  "estimation": 0,
  "last_updated": "2023-06-09"
}

出现的反序列化错误

收到Jackson反序列化错误:

no String-argument constructor/factory method to deserialize from String value ('{"name": "Powiat ząbkowicki", "population": {"2013": 67875, "2014": 67458, "2015": 66971, "2016": 66527, "2017": 66009, "2018": 65428, "2019": 64802, "2020": 62561, "2021": 61846, "2022": 61087}, "estimation": 0, "last_updated": "2023-06-09"}')] 

临时解决方法

添加带String参数的构造方法后问题解决:

public DummyEntity(String json) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        DummyEntity dummyEntity = objectMapper.readValue(json, DummyEntity.class);
        this.name = dummyEntity.name;
        this.population = dummyEntity.population;
        this.estimation = dummyEntity.estimation;
        this.lastUpdated = dummyEntity.lastUpdated;
    }

问题根源与解答

你遇到的问题根本不是实体类缺少Setter,而是Jackson接收到的输入格式不对:

  1. 实际输入是字符串而非JSON对象:错误信息明确显示Jackson试图把一个完整的JSON字符串直接反序列化成DummyEntity,这说明请求的Content-Type可能不是application/json(比如是text/plain),或者请求发送方错误地将JSON对象转成了字符串(比如前端重复调用JSON.stringify,导致整个JSON被包裹成了字符串)。

  2. Jackson的默认反序列化逻辑:当Jackson收到字符串类型的输入,而目标类没有对应的String参数构造方法或工厂方法时,就会抛出这个错误。你的实体类本身满足Jackson正常反序列化的要求(无参构造+公共Setter),只要输入是正确的JSON对象且Content-Type为application/json,不需要额外构造方法就能正常完成反序列化。

  3. 临时解决方法的本质:你添加的String构造方法相当于绕开了输入格式错误——把收到的字符串重新解析成JSON对象再赋值给实体类属性,这只是规避了问题,并非真正修复根源。

正确的解决方式是检查请求的Content-Type是否设置为application/json,同时确保请求发送方直接发送JSON对象而非字符串化后的JSON。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:10:39