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,手动完成反序列化步骤。
额外兼容要点
- 客户端用
LocalDate存储日期,服务端用String,需确保两者日期格式一致;或者服务端也改用LocalDate,并引入jackson-datatype-jsr310模块支持JSR310日期类型的序列化/反序列化。 - 服务端
Expense类的@JsonBackReference可能影响用户对象的反序列化,需确保User类能正确处理客户端传递的createdDateTime等字段。
内容的提问来源于stack exchange,提问作者chanze2
相关产品推荐
相关产品推荐

