Jenkins/groovy:如何用 null 漂亮地打印 net.sf.json.JSONObject?

Jenkins/groovy: How to pretty-print a net.sf.json.JSONObject with null?

在 Jenkins 管道上工作时,我观察到当我在 net.sf.json.JSONObject 上使用 JsonOutput.toJson() 时看起来像无限递归导致堆栈溢出,该 net.sf.json.JSONObject 吞噬了包含 null 的 JSON 字符串。

以下最少的代码演示了该问题:

// Jenkinsfile
@Library('libs@dev') libs

import groovy.json.JsonOutput

pipeline {
  agent any

  stages {
    stage( "json" ) {
      steps {
        script {
          my_lib.to_json_handbuilt_linkedhashmap()
          my_lib.to_json_readjson()
          my_lib.to_json_readjson_as_linkedhashmap()
        }
      }
    }
  }
}
// vars/my_lib.groovy
import groovy.json.JsonOutput

def asMap(j) {
  return j as LinkedHashMap
}

// This function is successful.
def to_json_handbuilt_linkedhashmap() {
  def d = [:]
  d.issues = null

  echo "---- handmade LinkedHashMap ----"
  echo "d ${d}"
  echo "d.getClass() ${d.getClass()}"
  echo "JsonOutput.toJson(d) ${JsonOutput.toJson(d)}"
}

// This function fails from infinite recursion causing a stack overflow.
def to_json_readjson() {
  def d = readJSON(text: '{ "issues" : null }')

  echo "---- readJSON ----"
  echo "d ${d}"
  echo "d.getClass() ${d.getClass()}"
  echo "JsonOutput.toJson(d) ${JsonOutput.toJson(d)}"
}

// This function also fails from infinite recursion causing a stack overflow.
def to_json_readjson_as_linkedhashmap() {
  def d = asMap(readJSON(text: '{ "issues" : null }'))

  echo "---- readJSON -> asMap ----"
  echo "d ${d}"
  echo "d.getClass() ${d.getClass()}"
  echo "JsonOutput.toJson(d) ${JsonOutput.toJson(d)}"
}

在上面的代码中,当使用 readJSON(text: '{ "issues" : null }') 返回的 net.sf.json.JSONObject 调用 JsonOutput.toJson() 时,to_json_readjson() 失败并出现堆栈溢出。 Jenkins 控制台输出在此 post.

的末尾

to_json_handbuilt_linkedhashmap()JsonOutput.toJson() 使用手工制作的 LinkedHashMap 调用时成功,相当于 { "issues" : null }.

最后,在 to_json_readjson_as_linkedhashmap() 中,当使用从 net.sf.json.JSONObject 创建的 LinkedHashMap 调用时,JsonOutput.toJson() 再次失败并出现堆栈溢出。

问题:
谁能解释一下当 readJSON() and/or JsonOutput.toJson() 与具有 null 的 JSON 字符串一起使用时导致堆栈溢出的原因?

因为我手工制作的LinkedHashMapJsonOutput.toJson()成功了,我以为问题是通过了JsonOutput.toJson()一个net.sf.json.JSONObject.
但我认为该理论已被排除,因为在 to_json_readjson_as_linkedhashmap() 中,我给 JsonOutput.toJson() 一个 LinkedHashMap,尽管它是从 net.sf.json.JSONObject.
创建的 问题似乎是我未能掌握的 readJSON() and/or JsonOutput.toJson() 的某种组合。

我试过了,但是已经放弃尝试使用 JsonSlurper,因为 I'm unable to even create an instance of one.

可能显示无限递归的(截断的)堆栈溢出错误:

Posting build status of FAILED to bitbucket.company.comjava.lang.WhosebugError
    at java.io.PrintStream.flush(PrintStream.java:338)
    at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:297)
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
    at java.util.logging.StreamHandler.flush(StreamHandler.java:259)
    at java.util.logging.ConsoleHandler.publish(ConsoleHandler.java:117)
    at java.util.logging.Logger.log(Logger.java:738)
    at java.util.logging.Logger.doLog(Logger.java:765)
    at java.util.logging.Logger.throwing(Logger.java:1447)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.getProperties(DefaultGroovyMethods.java:391)
    at groovy.json.JsonOutput.getObjectProperties(JsonOutput.java:327)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:320)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)
    at groovy.json.JsonOutput.writeMap(JsonOutput.java:458)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:321)

您能否通过使用 readJSONreturnPojo: true 参数来回避这个紧迫的问题,从而更快地解决您的整体任务?

获取普通的旧 null 对象而不是 net.sf.json.JSONNull 对象今天确实帮助了我,尽管我的问题涉及生成 CSV 而不是使用 JsonOutput。