【问题标题】:Groovy/Jenkins: how to prettify json string?Groovy/Jenkins:如何美化 json 字符串?
【发布时间】:2021-06-03 21:58:41
【问题描述】:

如何使用 Jenkins 声明式语法管道将 JSON 对象捕获为美化字符串?

pipeline {
  agent any

  stages {

    stage( "Set up" ) {
      steps {
        script {
          hostname    = "bld-machine"
          reply_email = "jenkins@${hostname}.company.com"
          actor_email = "user@company.com"
          status_json = initStatusJson()
        }
      }
    }

    /** Try figure out the difference between "global" and "env." variables. */
    stage( "Capture variables" ) {
      steps {
        script {
          status_json.env["var"]  = "${env.var}" as String
          status_json.env["var2"] = "${var}" as String
        }
      }
    }
  }

  post {
    always {
      script {
        def pretty_json = writeJSON( returnText: true, json: status_json )
      }
      emailext( subject: "CI/CD | ${currentBuild.currentResult}",
                from: "${reply_email}",
                to: "${actor_email}",
                mimeType: "text/plain",
                body: "${pretty_json}" )
    }
  }
}

def initStatusJson() {
  def json_obj = readJSON text: '{}'
  json_obj.job = readJSON text: '{}'
  json_obj.env = [:]
  json_obj.job.name = "${JOB_BASE_NAME}" as String
  json_obj.job.number = "${BUILD_ID}" as String
  json_obj.job.server = "${JENKINS_URL}" as String
  json_obj.job.visualization = "${JENKINS_URL}/blue/organizations/jenkins/${JOB_BASE_NAME}/detail/${JOB_BASE_NAME}/${BUILD_ID}/pipeline" as String

  return json_obj
}

上述Jenkinsfile中的def pretty_json =...语句触发如下错误:

WARNING: Unknown parameter(s) found for class type WARNING: Unknown parameter(s) found for class type 'org.jenkinsci.plugins.pipeline.utility.steps.json.WriteJSONStep': returnText
[Pipeline] }
[Pipeline] // script
Error when executing always post condition:
java.lang.IllegalArgumentException: You have to provided a file for writeJSON.
    at org.jenkinsci.plugins.pipeline.utility.steps.json.WriteJSONStepExecution.run(WriteJSONStepExecution.java:61)
    at org.jenkinsci.plugins.pipeline.utility.steps.json.WriteJSONStepExecution.run(WriteJSONStepExecution.java:43)
    at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

我尝试过的:

  1. def pretty_json = writeJSON( returnText: true, json: status_json ) 语句的灵感来自以下资源:
    Jenkinsfile pipeline construct JSON object and write to file
    https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#writejson-write-json-to-a-file-in-the-workspace

  2. 我也尝试了def pretty_json = writeJSON returnText: true, json: status_json,但结果相同。

  3. status_json.toString() 返回一个有效但未经美化的 JSON 字符串。

  4. 我在Create JSON strings from Groovy variables in Jenkins Pipeline的基础上尝试了def pretty_json = JsonOutput.toJson(status_json),它会产生这个错误:

Error when executing always post condition:
groovy.lang.MissingPropertyException: No such property: JsonOutput for class: groovy.lang.Binding
  1. 基于https://gist.github.com/osima/1161966 尝试了def pretty_json = groovy.json.JsonOutput.prettyPrint(status_json),它产生了这个错误:
Error when executing always post condition:
groovy.lang.MissingMethodException: No signature of method: java.lang.Class.prettyPrint() is applicable for argument types: (net.sf.json.JSONObject)

更新:尝试@daggett的解决方案如下:

  post {
    always {
      script {
        def pretty_json = status_json.toString(2)
      }
      emailext( subject: "CI/CD | ${currentBuild.currentResult}",
                from: "${reply_email}",
                to: "${actor_email}",
                mimeType: "text/plain",
                body: "${pretty_json}" )
    }
  }

...还尝试了一些变体,例如pretty_json = ...(而不是def pretty_json = ...),还将pretty_json 分配移到script{...} 范围之外...但没有任何效果。

script{...} 上下文中,.toString(2) 产生了这个错误:

Scripts not permitted to use method net.sf.json.JSON toString int.

script{...} 上下文之外,它产生了我解释为“语法错误”的内容:

WorkflowScript: 79: Expected a step @ line 79, column 7.
         pretty_json = status_json.toString(2)

【问题讨论】:

    标签: json jenkins groovy jenkins-pipeline jenkins-declarative-pipeline


    【解决方案1】:

    根据最后的错误信息

    groovy.lang.MissingMethodException: 
    No signature of method: java.lang.Class.prettyPrint() 
    is applicable for argument types: (net.sf.json.JSONObject)
    

    status_json 变量中有 net.sf.json.JSONObject

    这真的很奇怪 - 似乎你得到 status_json 不是 jenkins 的标准方式

    但是根据这个类的文档

    http://json-lib.sourceforge.net/apidocs/jdk15/net/sf/json/JSONObject.html#toString(int)

    只需执行以下操作即可制作漂亮的 json:

    def pretty_json = status_json.toString(2)
    

    如果你有Scripts not permitted to use method XYZ 异常:

    出于安全原因,很多非标准方法在 jenkins 中被禁用。

    请参阅此答案以解决此类问题:https://stackoverflow.com/a/39412951/1276664


    最后 - 您问题中的几乎所有案例都应该有效:

    1. writeJSON( returnText: true, json: status_json ) : 更新pipeline-utility-stepsjenkins插件到最新版本支持returnText参数

    2. 同上

    ...

    1. JsonOutput.toJson(status_json) : JsonOutput 类位于 groovy.json 包中。你可以在 t 导入这个包 他在脚本的开头import groovy.json 或这样称呼它:groovy.json.JsonOutput.toJson(status_json)。请注意,此方法返回非格式化的 json。

    2. groovy.json.JsonOutput.prettyPrint(status_json) :检查JsonOutput.prettyPrint 的文档 - 它可以被称为字符串而不是对象。所以这可以工作:groovy.json.JsonOutput.prettyPrint(status_json.toString()) 但只有在status_json.toString() 返回一个有效的 json 并且JsonOutput.prettyPrint 允许在詹金斯管理员中调用的情况下。

    【讨论】:

    • 看起来很有希望,但没有奏效——我用尝试这个答案的结果更新了我的帖子——也许这些错误对你很有意义,但我对语言的经验不够知道如何修复错误。
    • 脚本不允许 - 只需搜索此错误。这需要授予 jenkins 在 admin 中调用此方法。
    【解决方案2】:

    我刚刚做了一个测试,它给出了结果:
    def pretty_json = writeJSON( returnText: true, json: status_json , pretty: 4)
    注意:确保您安装了插件Pipeline Utility Steps。或者重新安装。
    下面是脚本示例:

    #!groovy
    import hudson.model.Result
    import groovy.json.*
    pipeline 
    {
        agent any 
        stages 
        {
            stage ('Set up')
            {
                steps
                {
                    script
                    {
                        hostname    = "bld-machine"
                        reply_email = "jenkins@${hostname}.company.com"
                        actor_email = "user@company.com"
                        status_json = initStatusJson()
                        println (status_json)
                    }
                }
            }
            stage ('Capture variables')
            {
                steps
                {
                    script
                    {
                        // Added just for test
                        status_json.env["var"]  = "Alt" as String
                        status_json.env["var2"]  = "su" as String
                        println (status_json)
                    }
                }
            }
        }
        
        post {
        always {
          script {
            def pretty_json = writeJSON( returnText: true, json: status_json , pretty: 4)
            println (pretty_json)
             emailext( subject: "CI/CD | ${currentBuild.currentResult}",
                    from: "${reply_email}",
                    to: "${actor_email}",
                    mimeType: "text/plain",
                    body: "${pretty_json}" )
           }
         }
        }
    } 
    def initStatusJson() {
      def json_obj = readJSON text: '{}'
      json_obj.job = readJSON text: '{}'
      json_obj.env = [:]
      json_obj.job.name = "${JOB_BASE_NAME}" as String
      json_obj.job.number = "${BUILD_ID}" as String
      json_obj.job.server = "${JENKINS_URL}" as String
      json_obj.job.visualization = "${JENKINS_URL}/blue/organizations/jenkins/${JOB_BASE_NAME}/detail/${JOB_BASE_NAME}/${BUILD_ID}/pipeline" as String
    
      return json_obj
    }
    

    输出日志:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-14
      • 2018-01-18
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2016-06-04
      • 2020-01-19
      • 1970-01-01
      相关资源
      最近更新 更多