Java使用Jackson解析JSON数组时出现类型不匹配异常的问询
解决Jackson解析JSON数组到Wrapper类的MismatchedInputException异常
问题场景
你有如下JSON数据:
[ { "Title": "New Moon in Sagittarius", "eventStartDate": "01/12/2024", "eventEndDate": "01/12/2024" }, { "Title": "Christmas", "eventStartDate": "25/12/2024", "eventEndDate": "25/12/2024" }, { "Title": "New Year's Eve", "eventStartDate": "31/12/2024", "eventEndDate": "31/12/2024" } ]
使用以下代码解析时:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.setDateFormat(new StdDateFormat().withLenient(false)); // Convert JSON string to Wrapper Class AstronomicalEventsWrapper wrapper = objectMapper.readValue (jsonString, AstronomicalEventsWrapper.class);
抛出异常:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.systicblanets.model.AstronomicalEventsWrapper` from Array value (token `JsonToken.START_ARRAY`) at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1767) at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1541) at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1488) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeFromArray(BeanDeserializer.java:656) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:211) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187) at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4899) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3846) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3814) at com.mysticplanets.schedulingtasks.CreateAstronomicalEventTask.sendMessage(CreateAstronomicalEventTask.java:60) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) at io.micrometer.observation.Observation.observe(Observation.java:499) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) at org.springframework.scheduling.config.Task$OutcomeTrackingRunnable.run(Task.java:83) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583)
你的AstronomicalEventsWrapper类代码:
import java.util.List; public class AstronomicalEventsWrapper { private List<AstronomicalEvent> astrologicalEvents; public List<AstronomicalEvent> getAstronomicalEvents() { return astrologicalEvents; } public void setAstronomicalEvents(List<AstronomicalEvent> astrologicalEvents) { this.astrologicalEvents = astrologicalEvents; } @Override public String toString() { return "AstronomicalEventsWrapper{" + "astrologicalEvents=" + astrologicalEvents + '}'; } }
错误原因
JSON的根节点是数组类型(用[]包裹),但你尝试将其反序列化成AstronomicalEventsWrapper这个单个对象,Jackson无法将数组直接转换为对象类型,因此抛出类型不匹配的异常。
解决方案
有两种可行的解决方式,根据你的需求选择:
方式一:修改JSON结构适配Wrapper类
将JSON调整为外层包含astrologicalEvents字段的对象结构,和AstronomicalEventsWrapper的属性对应:
{ "astrologicalEvents": [ { "Title": "New Moon in Sagittarius", "eventStartDate": "01/12/2024", "eventEndDate": "01/12/2024" }, { "Title": "Christmas", "eventStartDate": "25/12/2024", "eventEndDate": "25/12/2024" }, { "Title": "New Year's Eve", "eventStartDate": "31/12/2024", "eventEndDate": "31/12/2024" } ] }
修改后,原有的解析代码可以正常运行,因为JSON根节点现在是对象,和Wrapper类结构匹配。
方式二:修改解析代码直接解析为列表
如果无法修改JSON结构,直接将JSON数组解析为List<AstronomicalEvent>,再手动赋值给Wrapper类:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.setDateFormat(new StdDateFormat().withLenient(false)); // 直接解析为List<AstronomicalEvent>,使用TypeReference处理泛型 List<AstronomicalEvent> eventList = objectMapper.readValue( jsonString, new com.fasterxml.jackson.core.type.TypeReference<List<AstronomicalEvent>>() {} ); // 手动封装到Wrapper类中 AstronomicalEventsWrapper wrapper = new AstronomicalEventsWrapper(); wrapper.setAstronomicalEvents(eventList);
注意:这里必须使用TypeReference来传递泛型信息,因为Java的类型擦除机制,直接使用List.class无法让Jackson识别具体的元素类型。
另外,确保AstronomicalEvent类的字段与JSON中的键正确映射,比如JSON里的Title可以在类的字段上添加@JsonProperty("Title")注解来匹配大小写,或者开启Jackson的驼峰命名自动转换配置:
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE);
内容的提问来源于stack exchange,提问作者Nunyet Calçada
相关产品推荐
相关产品推荐

