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

使用Jackson JsonGenerator包装JSON列表时遇No ObjectCodec defined异常

解决Jackson JsonGenerator.writeTree()抛出No ObjectCodec defined异常

问题原因

你遇到的IllegalStateException: No ObjectCodec defined是因为创建的JsonGenerator没有绑定ObjectCodec,而writeTree(JsonNode)方法需要通过ObjectCodec完成JsonNode的序列化。直接用JsonFactory创建的JsonGenerator默认没有关联任何ObjectCodec,调用writeTree时就会报错。

另外代码里还有两个需要修正的细节:

  • 多余的jsonGenerator.writeRaw(":");会导致JSON格式错误,writeFieldName后直接调用writeTree会自动生成正确的键值分隔符
  • 字段名和期望结构不匹配:代码中type对应期望的isA,creationDate对应createdOn

修正后的代码

private InputStream generateJsonDocumentWrapper(final InputStream inputEventList) throws IOException {
    final PipedInputStream jsonDocumentWriter = new PipedInputStream();
    final PipedOutputStream out = new PipedOutputStream(jsonDocumentWriter);
    final ExecutorService executorService = Executors.newWorkStealingPool();
    final ObjectMapper objectMapper = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
    final JsonParser jsonParser = objectMapper.getFactory().createParser(inputEventList);
    final JsonNode node = jsonParser.readValueAsTree();

    executorService.execute(() -> {
        try (JsonGenerator jsonGenerator = objectMapper.getFactory().createGenerator(out)) {
            // 给JsonGenerator绑定ObjectCodec,这是解决异常的核心
            jsonGenerator.setCodec(objectMapper);
            
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("isA", "customerDocument"); // 修正字段名
            jsonGenerator.writeStringField("createdOn", Instant.now().toString()); // 修正字段名
            jsonGenerator.writeFieldName("customerBody");
            jsonGenerator.writeStartObject();
            jsonGenerator.writeFieldName("customerList");
            // 移除多余的writeRaw(":")
            jsonGenerator.writeTree(node);
            jsonGenerator.writeEndObject();
            jsonGenerator.writeEndObject();
            jsonGenerator.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            executorService.shutdown(); // 记得关闭线程池释放资源
        }
    });

    return jsonDocumentWriter;
}

更简洁的替代写法

其实可以直接用ObjectMapper构建整个JSON结构,不需要手动操作JsonGenerator,代码更易维护:

private InputStream generateJsonDocumentWrapper(final InputStream inputEventList) throws IOException {
    final ObjectMapper objectMapper = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
    final JsonNode customerListNode = objectMapper.readTree(inputEventList);

    // 构建包装结构的Node
    ObjectNode rootNode = objectMapper.createObjectNode();
    rootNode.put("isA", "customerDocument");
    rootNode.put("createdOn", Instant.now().toString());
    ObjectNode customerBodyNode = objectMapper.createObjectNode();
    customerBodyNode.set("customerList", customerListNode);
    rootNode.set("customerBody", customerBodyNode);

    // 将Node转为InputStream返回
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    objectMapper.writeValue(baos, rootNode);
    return new ByteArrayInputStream(baos.toByteArray());
}

这种方式不需要管道流和线程池,避免了多线程带来的潜在问题,可读性和维护性更强。

关键说明

  • 调用JsonGenerator.writeTree()时,必须通过setCodec(ObjectCodec)给生成器绑定有效的ObjectCodec(通常就是你的ObjectMapper实例)
  • 直接通过JsonFactory创建的JsonGenerator不会自动关联ObjectCodec,需要手动设置
  • 用ObjectNode构建JSON结构是Jackson的惯用写法,比手动操作JsonGenerator更简洁可靠

内容的提问来源于stack exchange,提问作者BATMAN_2008

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 12:10:23