MySQL读取JSON转换的方式


Posted in MySQL onMarch 18, 2022

存储

mysql5.7+开始支持存储JSON,后续不断优化,应用也越来越广泛
你可以自己将数据转换成Json String后插入,也可以选择使用工具,
而mybatis-plus就为此提供了非常简便的方式,
只需要在字段上加上 @TableField(typeHandler = XxxTypeHandler.class),
mybatis-plus就会自动帮你做转换,通用一般就两个:
   - com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler
   - com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler

例如

@Data
@TableName(autoResultMap = true)
public class Department implements Serializable {
    private static final long serialVersionUID = 203788572415896870L;
    @TableField(typeHandler = FastjsonTypeHandler.class)
    private List<Integer> userIds;
}

存在什么问题?

如果使用通用处理器,那对于基础类型以及对象来说没有什么问题。
但如果存储的字段类型是对象集合,那么当你取出来时,会发现集合中的对象都是JSONObject类型。
最常见的情况就拿出来进行遍历操作时,会抛出强转异常:
    java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to ...
因为处理器帮你转换时,并不会存储你集合的泛型,所以统统都按照Object类型来转换了:
    @Override
    protected Object parse(String json) {
        return JSON.parseObject(json, type);
    }

例如下面这种形式的类:

@Data
@TableName(autoResultMap = true)
public class Department implements Serializable {

    private static final long serialVersionUID = 203788572415896870L;
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @TableField(typeHandler = FastjsonTypeHandler.class)
    private List<User> users;
    @Data
    public static class USer implements Serializable {
        // ...
    }
}

如何处理

方式一:自定义处理器,自己做类型转换,这也是当前最普遍的方式,但是对于存在List字段的对象,还需要在XxxMapper.xml中进行resultMap配置

@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListFastJsonTypeHandler extends FastjsonTypeHandler {

    private final Class<? extends Object> type;
    public ListFastJsonTypeHandler(Class<?> type) {
        super(type);
        this.type = type;
    }
    /**
     * 自己将json转换成list
     * @param json
     * @return
     */
    @Override
    protected Object parse(String json) {
        return JSON.parseArray(json, this.type);
}
<mapper namespace="com.xxx.cn.mapper.DepartmentMapper">
    <resultMap id="BaseResultMap" type="com.xxx.cn.domain.Department">
        <id property="id" column="id"/>
        <result property="users" column="users" jdbcType="VARCHAR"
                javaType="com.xxx.cn.domain.Department.User"
                typeHandler="com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler"/>
    </resultMap>
</mapper>

配置完成后,ListFastJsonTypeHandler就会将json转换成javaType对应的对象集合了

方式二:配置一个Mybatis插件,拦截ResultSetHandler,将返回结果进行处理。 这样的好处就是不用写自定义的处理器和在XxxMapper.xml中做配置,减少了工作

@Component
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class ResultSetInterceptor implements Interceptor {

    /**
     * json序列化规则
     */
    private final SerializerFeature[] serializerFeatures = {
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullListAsEmpty,
            SerializerFeature.WriteNullStringAsEmpty
    };
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed = invocation.proceed();
        if (containJSONObject(proceed)) {
            if (proceed instanceof Collection) {
                return JSON.parseArray(JSON.toJSONString(proceed, serializerFeatures), ((Collection<?>) proceed).toArray()[0].getClass());
            }
            return JSON.parseObject(JSON.toJSONString(proceed, serializerFeatures), proceed.getClass());
        }
//        if (proceed instanceof Collection) {
//            for (Object obj : ((Collection<?>) proceed)) {
//                parseJSON2Object(obj, obj.getClass());
//            }
//        } else {
//            parseJSON2Object(proceed, proceed.getClass());
//        }
        return proceed;
    }
     * 将返回数据中心的JSONObject对象转换成正常的对象
     *
     * @param obj
     * @param typeClass
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
    private void parseJSON2Object(Object obj, Class<?> typeClass) throws IllegalAccessException, ClassNotFoundException {
        for (Field declaredField : typeClass.getDeclaredFields()) {
            declaredField.setAccessible(true);
            Object value = declaredField.get(obj);
            if (isNullValueField(value)) {
                continue;
            Type genericType = declaredField.getGenericType();
            String fieldClassName = genericType.getTypeName();
            if (genericType instanceof ParameterizedType) {
                fieldClassName = ((ParameterizedType) genericType).getActualTypeArguments()[0].getTypeName();
            if (containJSONObject(value)) {
                if (value instanceof Collection) {
                    declaredField.set(obj, JSON.parseArray(JSON.toJSONString(value, serializerFeatures), Class.forName(fieldClassName)));
                } else {
                    declaredField.set(obj, JSON.parseObject(JSON.toJSONString(value, serializerFeatures), Class.forName(fieldClassName)));
                }
     * 判断是否跳过字段
     * @param value
     * @return
    private Boolean isNullValueField(Object value) {
        return null == value || "".equals(String.valueOf(value).trim())
                || (value instanceof Collection && ((Collection<?>) value).size() == 0);
     * 判断值是否包含JSONObject对象
    private boolean containJSONObject(Object value) throws IllegalAccessException {
        if (isNullValueField(value)) {
            return false;
        if (value instanceof Collection) {
            for (Object obj : (Collection<?>) value) {
                if (obj instanceof JSONObject) {
                    return true;
                if (obj instanceof Collection && containJSONObject(obj)) {
                    for (Field declaredField : obj.getClass().getDeclaredFields()) {
                        declaredField.setAccessible(true);
                        Object fieldValue = declaredField.get(obj);
                        if (isNullValueField(fieldValue)) {
                            continue;
                        }
                        if (fieldValue instanceof JSONObject) {
                            return true;
                        if (fieldValue instanceof Collection && containJSONObject(fieldValue)) {
                    }
        return value instanceof JSONObject;
}

到此这篇关于MySQL读取JSON转换的文章就介绍到这了,更多相关MySQL读取JSON转换内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
如何设计高效合理的MySQL查询语句
May 26 MySQL
MySQL 数据类型选择原则
May 27 MySQL
你知道哪几种MYSQL的连接查询
Jun 03 MySQL
Mysql中存储引擎的区别及比较
Jun 04 MySQL
mysql中between的边界,范围说明
Jun 08 MySQL
安装配置mysql及Navicat prenium的详细流程
Jun 10 MySQL
MySQL 发生同步延迟时Seconds_Behind_Master还为0的原因
Jun 21 MySQL
浅析MySQL如何实现事务隔离
Jun 26 MySQL
深入解析MySQL索引数据结构
Oct 16 MySQL
MySQL悲观锁与乐观锁的实现方案
Nov 02 MySQL
MySQL图形化管理工具Navicat安装步骤
Dec 04 MySQL
分享很少见很有用的SQL功能CORRESPONDING
Aug 05 MySQL
分享MySQL常用 内核 Debug 几种常见方法
Mar 17 #MySQL
MySQL如何快速创建800w条测试数据表
Mar 17 #MySQL
利用JuiceFS使MySQL 备份验证性能提升 10 倍
MySQL 分区表中分区键为什么必须是主键的一部分
MySQL优化及索引解析
一条 SQL 语句执行过程
Mysql事务索引知识汇总
Mar 17 #MySQL
You might like
S900/ ETON E1-XM 收音机
2021/03/02 无线电
php读取msn上的用户信息类
2008/12/05 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
php查看请求头信息获取远程图片大小的方法分享
2013/12/25 PHP
PHP基于接口技术实现简单的多态应用完整实例
2017/04/26 PHP
JS操作XML中DTD介绍及使用方法分析
2019/07/04 PHP
快速保存网页中所有图片的方法
2006/06/23 Javascript
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
javascript与CSS复习(《精通javascript》)
2010/06/29 Javascript
js格式化金额可选是否带千分位以及保留精度
2014/01/28 Javascript
Jquery焦点与失去焦点示例应用
2014/06/10 Javascript
原生js实现jquery函数animate()动画效果的简单实例
2016/08/21 Javascript
微信小程序 HTTPS报错整理常见问题及解决方案
2016/12/14 Javascript
一句jQuery代码实现返回顶部效果(简单实用)
2016/12/28 Javascript
Javascript实现base64的加密解密方法示例
2017/06/27 Javascript
webpack构建vue项目的详细教程(配置篇)
2017/07/17 Javascript
Nodejs+angularjs结合multiparty实现多图片上传的示例代码
2017/09/29 NodeJs
基于webpack4.X从零搭建React脚手架的方法步骤
2018/12/23 Javascript
JS实现拼图游戏
2021/01/29 Javascript
js实现随机点名功能
2020/12/23 Javascript
Python random模块(获取随机数)常用方法和使用例子
2014/05/13 Python
python的keyword模块用法实例分析
2015/06/30 Python
python中的错误处理
2016/04/10 Python
Python中enumerate函数代码解析
2017/10/31 Python
python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序
2020/07/20 Python
Python中交换两个元素的实现方法
2018/06/29 Python
selenium+python自动化测试之页面元素定位
2019/01/23 Python
python3实现表白神器
2019/04/09 Python
Python实现把类当做字典来访问
2019/12/16 Python
TensorFlow查看输入节点和输出节点名称方式
2020/01/04 Python
Pycharm+Python工程,引用子模块的实现
2020/03/09 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
材料成型专业个人求职信范文
2013/09/25 职场文书
武夷山导游词
2015/02/03 职场文书
摘录式读书笔记
2015/07/01 职场文书
写作技巧:如何撰写一份优秀的营销策划书
2019/08/13 职场文书