背景介绍
由于 Java 本身语言特性,Mybatis Plus 使用的 FastjsonTypeHandler 以及 JacksonTyoeHandler 虽然能够解析 List,但是却无法解析 List
所以会出现极其尴尬的情况,你本来具体的类型是 T,但是它硬生生在你的 List 里面存放了 JSONObject,你会发现你完全没法操作你的 List,只能眼巴巴的看着它(雾
10:43:54.339 [pool-8-thread-1] ERROR cn.edu.hnuahe.mountain.common.managers.ExceptionManager - Oops!
java.lang.ClassCastException: class com.alibaba.fastjson.JSONObject cannot be cast to class cn.edu.hnuahe.mountain.service.planet.mercury.entities.models.Question$Option (com.alibaba.fastjson.JSONObject and cn.edu.hnuahe.mountain.service.planet.mercury.entities.models.Question$Option are in unnamed module of loader 'app')
at cn.edu.hnuahe.mountain.service.planet.mercury.services.JudgeService.handle(JudgeService.java:59)
at cn.edu.hnuahe.mountain.service.planet.mercury.http.controller.EvaluationProxyImpl.createSubmitted(EvaluationProxyImpl.java:156)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.noear.solon.core.wrap.MethodWrap.invoke(MethodWrap.java:183)
at org.noear.solon.core.wrap.MethodWrap.doIntercept(MethodWrap.java:175)
at org.noear.solon.core.aspect.InterceptorEntity.doIntercept(InterceptorEntity.java:26)
at org.noear.solon.core.aspect.Invocation.invoke(Invocation.java:78)
at cn.edu.hnuahe.mountain.common.providers.InterceptorServiceProvider.lambda$new$0(InterceptorServiceProvider.java:66)
at org.noear.solon.core.aspect.InterceptorEntity.doIntercept(InterceptorEntity.java:26)
at org.noear.solon.core.aspect.Invocation.invoke(Invocation.java:78)
at org.noear.solon.core.wrap.MethodWrap.invokeByAspect(MethodWrap.java:199)
at org.noear.solon.core.handle.ActionExecutorDefault.execute(ActionExecutorDefault.java:43)
at org.noear.solon.core.handle.Action.callDo(Action.java:297)
at org.noear.solon.core.handle.Action.invoke0(Action.java:239)
at org.noear.solon.core.handle.Action.invoke(Action.java:169)
at org.noear.solon.core.handle.Action.handle(Action.java:148)
at org.noear.solon.core.route.RouterHandler.handleOne(RouterHandler.java:81)
at org.noear.solon.core.route.RouterHandler.handle(RouterHandler.java:46)
at org.noear.solon.SolonApp.doFilter(SolonApp.java:664)
at org.noear.solon.core.handle.FilterChainNode.doFilter(FilterChainNode.java:22)
at org.noear.solon.logging.integration.XPluginImp.lambda$loadAppenderConfig$1(XPluginImp.java:47)
at org.noear.solon.core.handle.FilterChainNode.doFilter(FilterChainNode.java:22)
at org.noear.solon.SolonApp.tryHandle(SolonApp.java:633)
at org.noear.solon.socketd.SocketContextHandler.handle(SocketContextHandler.java:31)
at org.noear.solon.socketd.ListenerProxy.onMessage0(ListenerProxy.java:157)
at org.noear.solon.socketd.ListenerProxy.lambda$onMessage$1(ListenerProxy.java:117)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
解决方案
思路:强行将 JSONArray 放入 JSONArray 中,然后遍历 JSONArray 拿到 JSONObject 转换为需要的类型并放回原数组。
这里使用了 JOOR 链式反射框架,超好用,强烈推荐!
/**
* Mybatis Plus 自动解析 JSON 类型异常修正器
*
* @param origin 由 Mybatis Plus 生成出来的有问题的数组
* @param target 要转换成的类型
*/
protected <T> void recover(List<T> origin, Class<T> target) {
JSONArray options = Reflect.onClass(JSONArray.class)
.create(origin)
.get();
for (int i = 0; i < options.size(); i++) {
if (options.get(i) instanceof JSONObject metadata) {
origin.set(
i,
metadata.toJavaObject(target)
);
}
}
}