You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

  1. 编写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;
    }
}
  1. 绑定到对应字段:如果使用jOOQ代码生成,在生成配置中为loadArray01字段指定上述Converter;如果是runtime使用,查询时调用.convertUsing()方法指定转换器即可。

方案2:POJO字段添加自定义反序列化注解

仅需修改对应POJO字段,无需调整jOOQ配置:

  1. 编写自定义反序列化器:
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);
    }
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:27:00