在使用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
}
这样,会不会很优雅,希望对后面的同学有帮助,有问题,请随时留言!

401

被折叠的 条评论
为什么被折叠?



