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知识点整理
Apr 05 MySQL
MySQL 全文索引使用指南
May 25 MySQL
MYSQL主从数据库同步备份配置的方法
May 26 MySQL
MySQL中日期型单行函数代码详解
Jun 21 MySQL
为什么MySQL选择Repeatable Read作为默认隔离级别
Jul 26 MySQL
一篇文章带你深入了解Mysql触发器
Aug 02 MySQL
MySQL分库分表详情
Sep 25 MySQL
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 MySQL
Mysql 8.x 创建用户以及授予权限的操作记录
Apr 18 MySQL
解决Mysql报错 Table 'mysql.user' doesn't exist
May 06 MySQL
Mysql索引失效 数据库表中有索引还是查询很慢
May 15 MySQL
MySQL约束(创建表时的各种条件说明)
Jun 21 MySQL
分享MySQL常用 内核 Debug 几种常见方法
Mar 17 #MySQL
MySQL如何快速创建800w条测试数据表
Mar 17 #MySQL
利用JuiceFS使MySQL 备份验证性能提升 10 倍
MySQL 分区表中分区键为什么必须是主键的一部分
MySQL优化及索引解析
一条 SQL 语句执行过程
Mysql事务索引知识汇总
Mar 17 #MySQL
You might like
php5.3中连接sqlserver2000的两种方法(com与ODBC)
2012/12/29 PHP
测试PHP连接MYSQL成功与否的代码
2013/08/16 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
Laravel 框架返回状态拦截代码
2019/10/18 PHP
javascript IE中的DOM ready应用技巧
2008/07/23 Javascript
javascript 可以拖动的DIV(二)
2009/06/26 Javascript
深入理解javascript学习笔记(一) 编写高质量代码
2012/08/09 Javascript
JQuery each()函数如何优化循环DOM结构的性能
2012/12/10 Javascript
通过上下左右键和回车键切换光标实现代码
2013/03/08 Javascript
javascript实现文字图片上下滚动的具体实例
2013/06/28 Javascript
省市联动效果的简单实现代码(推荐)
2016/06/06 Javascript
Angular ng-repeat 对象和数组遍历实例
2016/09/14 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
jquery ui sortable拖拽后保存位置
2017/04/27 jQuery
jQuery常见面试题之DOM操作详析
2017/07/05 jQuery
swiper在vue项目中loop循环轮播失效的解决方法
2018/09/15 Javascript
微信小程序实现简单评论功能
2018/11/28 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
2019/05/10 Javascript
js实现转动骰子模型
2019/10/24 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
Python利用BeautifulSoup解析Html的方法示例
2017/07/30 Python
python opencv minAreaRect 生成最小外接矩形的方法
2019/07/01 Python
python 将日期戳(五位数时间)转换为标准时间
2019/07/11 Python
python绘制雪景图
2019/12/16 Python
Python关键字及可变参数*args,**kw原理解析
2020/04/04 Python
使用Pycharm在运行过程中,查看每个变量的操作(show variables)
2020/06/08 Python
一文读懂python Scrapy爬虫框架
2021/02/24 Python
分享30个新鲜的CSS3打造的精美绚丽效果(附演示下载)
2012/12/28 HTML / CSS
澳洲国民品牌乡村路折扣店:Country Road & Trenery Outlet
2018/04/19 全球购物
法律专业自我鉴定
2013/10/03 职场文书
师范大学音乐表演专业求职信
2013/10/23 职场文书
旅游管理毕业生自荐信范文
2014/03/19 职场文书
村主任个人对照检查材料
2014/10/01 职场文书
网球场地租赁协议范本
2014/10/07 职场文书
研究生毕业登记表的自我鉴定范文
2019/07/15 职场文书