当前位置: 首页 > news >正文

Jenkins Pipeline 中的 NotSerializableException: LazyMap 报错 | 3个实用解决方案

大家好!在使用 Jenkins Pipeline 时,你是否遇到过类似以下的报错?

NotSerializableException: groovy.json.internal.LazyMap

这个看似棘手的异常,其实与 Groovy 版本的更新有关。简单来说,从Groovy 2.3起(Jenkins 2.7.1 所用的是 2.4.7),默认的JsonSlurper在解析 JSON 时会返回一种叫LazyMap的结构。它虽然节省内存,却不支持序列化,而 Pipeline 在执行中经常需要序列化数据,因此直接使用就容易抛出异常。

常见问题代码如下:

def jsonResponse = sh(script: 'curl -s http://example.com/api/data', returnStdout: true).trim() def jsonSlurper = new groovy.json.JsonSlurper() def result = jsonSlurper.parseText(jsonResponse) // 这里得到的是 LazyMap println(result) // 触发 NotSerializableException!

别担心,下面为大家分享三个实用的解决方案,帮你轻松绕过此坑。

方案适用场景备注
@NonCPS 注解推荐首选,逻辑独立、不需与 Pipeline 步骤交互时最清晰、最规范
转换为 HashMap只需简单转换,数据结构较平坦时注意嵌套结构的拷贝问题
改用脚本式流水线已在脚本式环境中,或声明式限制过多时灵活,但需注意代码风格统一

简单来说,遇到LazyMap导致的序列化错误时,优先考虑使用@NonCPS注解封装解析逻辑,这通常是最干净、最可持续的做法。


解决方案一:使用 @NonCPS 注解(推荐)

这是最直接、最推荐的做法。
通过在方法上添加@NonCPS注解,可以告诉 Jenkins 这个方法内的操作不需要参与序列化,从而允许使用LazyMap等非序列化对象。

示例:

@NonCPS def parseJson(String jsonText) { return new groovy.json.JsonSlurper().parseText(jsonText) } node { def jsonResponse = sh(script: 'curl -s http://example.com/api/data', returnStdout: true).trim() def result = parseJson(jsonResponse) // 安全,不会触发异常 println(result) }

小贴士:
@NonCPS方法内应尽量保持纯 Groovy 逻辑,避免调用 Jenkins Pipeline 的步骤(如sh,echo等)。


解决方案二:将 LazyMap 转换为可序列化的 Map

如果不想用@NonCPS,也可以手动将LazyMap转换为标准的、可序列化的HashMap

示例:

def jsonResponse = sh(script: 'curl -s http://example.com/api/data', returnStdout: true).trim() def jsonSlurper = new groovy.json.JsonSlurper() def lazyMap = jsonSlurper.parseText(jsonResponse) def serializableMap = new HashMap<>(lazyMap) // 关键转换 println(serializableMap) // 现在可以安全使用了

注意:这种方式对于嵌套较深的 JSON 结构是浅拷贝,如果内层仍有LazyMap,可能仍需递归转换。


解决方案三:改用脚本式流水线(Scripted Pipeline)

如果你在使用声明式流水线(Declarative Pipeline),可以尝试在特定阶段切回脚本式流水线写法。脚本式流水线在序列化控制上更为灵活,有时能自然规避此类问题。

示例:

node { stage('Process JSON') { def jsonResponse = sh(script: 'curl -s http://example.com/api/data', returnStdout: true).trim() def jsonSlurper = new groovy.json.JsonSlurper() def result = jsonSlurper.parseText(jsonResponse) println(result.key) // 在脚本式块内通常可直接使用 } }
-------------------------------------- 🚀 Powered by Moshow 郑锴- 🌟 Might the holy code be with you!-------------------------------------🔍 公众号 👉 软件开发大百科💻 CSDN 👉 https://zhengkai.blog.csdn.net📂 GitHub 👉 https://github.com/moshowgame

http://www.jsqmd.com/news/276232/

相关文章:

  • 统一数据访问平台设计方案 - DataHub
  • 开源语音情感识别新选择:Emotion2Vec+ Large落地应用趋势解析
  • 什么是MES?一文看懂MES的主要功能
  • 3步轻松实现原神帧率解锁:告别60帧限制的完整指南
  • verl early stopping机制:防止过拟合的部署配置
  • 参考资料哪里找?GLM-TTS官方文档精要整理
  • Sharp-dumpkey创新方案:微信数据库密钥安全提取深度解析
  • 一键部署verl:5分钟搞定强化学习环境
  • 从Excel到知识网络:SmartKG零代码智能图谱构建全攻略
  • GPU Burn终极指南:多GPU压力测试完整教程
  • Glyph工业质检应用:缺陷图像分类系统部署案例
  • GPEN能否跑在树莓派上?ARM架构移植实验记录
  • verl自动扩缩容:基于负载的GPU资源调整实战
  • 原神帧率突破:开启高刷新率的视觉革命
  • 开发者必看:PyTorch-2.x预装依赖镜像免配置部署推荐
  • Qwen3-Embedding-0.6B推理卡顿?显存优化部署实战案例分享
  • Qwen3-0.6B容器化部署:Docker镜像定制与K8s编排实践
  • 输入‘你是谁’,它回答‘由我开发’——太震撼了
  • Live Avatar跑不动?5×24GB显卡无法运行的底层原因揭秘
  • Hunyuan-MT-7B显存溢出?量化压缩部署实战解决方案
  • Z-Image-Edit文本渲染能力测试:中英文排版准确性分析
  • 流式输出怎么实现?Qwen3-0.6B + streaming实测
  • 噪声误判为语音?一招教你调整FSMN VAD阈值
  • Z-Image-Turbo真实感生成实战:人物肖像文生图详细教程
  • VibeThinker-1.5B教育科技案例:在线编程课AI助教系统
  • fft npainting lama更新日志解析:v1.0.0核心功能亮点
  • FSMN VAD嵌入式设备可行性:树莓派部署设想
  • Qwen3-1.7B实战体验:从0搭建AI对话系统
  • GPT-OSS-20B节省成本:动态GPU分配部署实践
  • 5分钟部署Qwen-Image-2512-ComfyUI,AI去水印一键搞定