背景介绍

由于 Java 本身语言特性,Mybatis Plus 使用的 FastjsonTypeHandler 以及 JacksonTyoeHandler 虽然能够解析 List,但是却无法解析 List 中 T 的具体类型。
所以会出现极其尴尬的情况,你本来具体的类型是 T,但是它硬生生在你的 List 里面存放了 JSONObject,你会发现你完全没法操作你的 List,只能眼巴巴的看着它(雾

现场 x1

现场 x2

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)
                );
            }
        }
    }
最后修改:2022 年 03 月 26 日
如果觉得我的文章对你有用,请随意赞赏