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

Jackson MismatchedInputException问题:SocketIO传输Expense对象失败

问题:Jackson反序列化Expense对象失败

我正在为学校项目开发一个基于Java、JavaFX、SocketIO和Hibernate的应用,现在遇到了Jackson反序列化失败的问题。

服务端Expense类:

@Entity
@Table(name = "expenses")
@Data
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Expense {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(nullable = false, updatable = false)
    @CreationTimestamp
    private Date createdDateTime;

    private String name;

    @ManyToOne
    @JsonBackReference
    @JsonProperty("user")
    @JoinColumn(referencedColumnName = "id", name = "user_id")
    private User user;

    private double amount;

    @Enumerated(EnumType.STRING)
    private ExpenseType type;

    private String description;

    private String date;

    public Expense() {
    }
}

客户端Expense类:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class Expense {
    @JsonIgnore
    private long id;
    private String name;
    private User user;
    private double amount;

    private ExpenseType type;
    private String description;
    private LocalDate date;

    public Expense(String name, User user, double amount, ExpenseType type, String description, LocalDate date) {
        this.name = name;
        this.user = user;
        this.amount = amount;
        this.type = type;
        this.description = description;
        this.date = date;
    }
}

错误信息:

[nioEventLoopGroup-3-3] ERROR com.corundumstudio.socketio.JsonSupportWrapper - Can't read value: ["create_expense","{\"name\":\"test\",\"user\":{\"id\":1,\"createdDateTime\":\"2024-04-01T14:56:32.000+00:00\",\"username\":\"admin\",\"role\":\"ADMIN\"},\"amount\":123.0,\"type\":\"EXPENSE\",\"description\":\"\",\"date\":\"2024-04-08\"}"] for type: class com.corundumstudio.socketio.protocol.Event
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `dev.lukaslist.models.Expense` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{\"name\":\"test\",\"user\":{\"id\":1,\"createdDateTime\":\"2024-04-01T14:56:32.000+00:00\",\"username\":\"admin\",\"role\":\"ADMIN\"},\"amount\":123.0,\"type\":\"EXPENSE\",\"description\":\"\",\"date\":\"2024-04-08\"}')
 at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 19]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    ...(省略后续堆栈信息)

解决方案

从错误信息和传入的数据格式可以明确:SocketIO事件的第二个参数是JSON字符串,而非直接的JSON对象。Jackson尝试将这个字符串直接反序列化为Expense实例,但Expense类没有接收字符串的构造方法,因此触发报错。

方法1:修正客户端发送逻辑

客户端发送事件时,不要手动将Expense对象序列化为字符串,直接传递对象本身。SocketIO会自动处理对象的序列化,服务端将收到标准JSON对象,Jackson可直接完成反序列化:

// 错误写法:手动转成字符串发送
String expenseJson = objectMapper.writeValueAsString(expense);
socket.emit("create_expense", expenseJson);

// 正确写法:直接发送对象
socket.emit("create_expense", expense);

方法2:服务端手动解析字符串

如果客户端无法修改发送方式,服务端可以先接收字符串,再手动反序列化为Expense对象:

@OnEvent("create_expense")
public void handleCreateExpense(SocketIOClient client, String expenseJson) {
    ObjectMapper mapper = new ObjectMapper();
    try {
        Expense expense = mapper.readValue(expenseJson, Expense.class);
        // 后续业务逻辑处理
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
}

注意要将事件处理方法的参数类型从Expense改为String,手动完成反序列化步骤。

额外兼容要点

  1. 客户端用LocalDate存储日期,服务端用String,需确保两者日期格式一致;或者服务端也改用LocalDate,并引入jackson-datatype-jsr310模块支持JSR310日期类型的序列化/反序列化。
  2. 服务端Expense类的@JsonBackReference可能影响用户对象的反序列化,需确保User类能正确处理客户端传递的createdDateTime等字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:25:00