Jackson反序列化MariaDB JSON_ARRAY列到List<Integer>报错如何解决
问题根因
MariaDB的JSON类型本质是带json_valid约束的longtext,jOOQ默认不会将其识别为JSON结构,查询返回的是包裹了JSON数组字符串的TextNode对象,Jackson默认的反序列化逻辑不会自动解析TextNode内部的字符串内容为List,因此抛出类型转换异常。
解决方案
方案1:自定义jOOQ类型转换器(推荐,全局生效)
自定义jOOQ Converter实现longtext到List<Integer>的自动转换,jOOQ代码生成阶段即可绑定对应字段,无需额外处理POJO。
- 编写Converter实现:
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.jooq.Converter; import java.util.List; public class JsonIntListConverter implements Converter<String, List<Integer>> { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final TypeReference<List<Integer>> TYPE_REFERENCE = new TypeReference<List<Integer>>() {}; @Override public List<Integer> from(String databaseValue) { if (databaseValue == null) return null; try { return OBJECT_MAPPER.readValue(databaseValue, TYPE_REFERENCE); } catch (Exception e) { throw new RuntimeException("JSON数组反序列化失败", e); } } @Override public String to(List<Integer> userValue) { if (userValue == null) return null; try { return OBJECT_MAPPER.writeValueAsString(userValue); } catch (Exception e) { throw new RuntimeException("List序列化JSON失败", e); } } @Override public Class<String> fromType() { return String.class; } @Override public Class<List<Integer>> toType() { return (Class) List.class; } }
- 绑定到对应字段:如果使用jOOQ代码生成,在生成配置中为
loadArray01字段指定上述Converter;如果是runtime使用,查询时调用.convertUsing()方法指定转换器即可。
方案2:POJO字段添加自定义反序列化注解
仅需修改对应POJO字段,无需调整jOOQ配置:
- 编写自定义反序列化器:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.node.TextNode; import java.io.IOException; import java.util.List; public class TextNodeIntListDeserializer extends StdDeserializer<List<Integer>> { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final TypeReference<List<Integer>> TYPE_REFERENCE = new TypeReference<List<Integer>>() {}; public TextNodeIntListDeserializer() { super(List.class); } @Override public List<Integer> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node instanceof TextNode) { // 解析TextNode内部的JSON数组字符串 return OBJECT_MAPPER.readValue(node.asText(), TYPE_REFERENCE); } // 已经是JSON数组节点直接转换 return p.getCodec().treeToValue(node, TYPE_REFERENCE); } }
- POJO字段添加注解:
@JsonDeserialize(using = TextNodeIntListDeserializer.class) private List<Integer> loadArray01;
方案3:临时手动转换
如果仅个别场景需要使用,无需全局配置,可在获取结果后手动转换:
String jsonStr = record.get("loadArray01").toString(); List<Integer> loadArray01 = new ObjectMapper().readValue(jsonStr, new TypeReference<List<Integer>>() {});
内容的提问来源于stack exchange,提问作者Stefano Bossi
相关产品推荐
相关产品推荐

