如何使用JacksonTypeHandler处理mysql json字符串转List对象的问题

该文章已生成可运行项目,

在使用mysql5.7或更高版本时,json类型字段应用场景越来越多,对于普通的对象或者List<Integer>、List<String>这些基础类型,jacksonTypeHandler都能很好的处理,如下:

1、定义一个person对象

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class Person {
    @JsonProperty("id")
    private Long id;

    @JsonProperty("name")
    private String name;

    @JsonProperty("age")
    private Integer age;
}

2、定义映射关系

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;

@Data
@TableName(value = "your_table", autoResultMap = true)
public class YourEntity {
    private Long id;

    // JSON 字段映射为 Person 对象
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Person person;

    // JSON 字段映射为 List<String>
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> stringList;
}

通过上述两步,基本就可以解决json字段的处理,但json字段是一个列表,如List<Person>对象,上面的代码是有问题的,因为Jackson 在反序列化时,需要明确的目标类型信息来正确地将 JSON 数据映射到 Java 对象。如果没有明确的类型信息,Jackson 默认会将 JSON 数组解析为 List<LinkedHashMap>,因为 LinkedHashMap 是 Jackson 默认的 Map 类型。下面就是我们给出的解决方案:

1、创建一个自定义类的注解JsonType

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonType {
    Class<?> value();
}

2、创建一个通过的ListTypeHandler的实现类

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JsonListTypeHandler extends BaseTypeHandler<Object> {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        try {
            ps.setString(i, objectMapper.writeValueAsString(parameter));
        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize JSON", e);
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json);
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJson(json);
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return parseJson(json);
    }

    private Object parseJson(String json) {
        if (json == null || json.trim().isEmpty()) {
            return null;
        }
        try {
            // 获取字段的类型信息
            JsonType jsonType = field.getAnnotation(JsonType.class);
            if (jsonType != null) {
                return objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, jsonType.value()));
            }
            return objectMapper.readValue(json, Object.class);
        } catch (Exception e) {
            throw new RuntimeException("Failed to parse JSON", e);
        }
    }
}

3,接下来,你就可以使用它了

@TableName(autoResultMap = true)
public class YourEntity {
    private Long id;

    @TableField(typeHandler = JsonListTypeHandler.class)
    @JsonType(Person.class)
    private List<Person> personList;

    // Getters and Setters
}

这样,会不会很优雅,希望对后面的同学有帮助,有问题,请随时留言!

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值