开发者问题收集

Groovy/Jenkins:如何美化 json 字符串?

2021-06-03
6087

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

pipeline {
  agent any

  stages {

    stage( "Set up" ) {
      steps {
        script {
          hostname    = "bld-machine"
          reply_email = "jenkins@${hostname}.company.com"
          actor_email = "[email protected]"
          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 管道构造 JSON 对象并写入文件
    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. 我尝试了 def pretty_json = JsonOutput.toJson(status_json) ,基于 在 Jenkins Pipeline 中从 Groovy 变量创建 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)
2个回答

根据最后一个错误消息

681797382

您有 net.sf.json.jsonobject in status> status_json variable。

140527360

但是,根据此类的文档

http://json-lib.sourceforge.net/apidocs/jdk15/net/net/net/net/net/net/sf/sf/json/json/json/jsonobject.ht.htmlllunptring( int)

仅按照以下操作来制作漂亮的JSON:

894557569

如果您没有 脚本不允许脚本使用方法xyz 例外:

出于安全原因,詹金斯(Jenkins href =“ https://stackoverflow.com/a/39412951/1276664”> https://stackoverflow.com/a/a/39412951/1276664 您的问题的每种情况都应该有效:

  1. 写入JSON(returnText:true,json:status_json) : 更新 pipeline-utility-steps jenkins plugin to jenkins plugin to to Support returnText 参数

  2. 与上述相同

...

  1. jsonoutput.tojson(status_json) jsonOutput groovy.json 软件包中的类。您可以在T中导入此软件包 他开始脚本 导入groovy.json 或这样称呼: grovy.json.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中调用。

daggett
2021-06-03

我刚刚做了一个测试,结果如下:
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 = "[email protected]"
                    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
}

输出日志: 在此处输入图片说明

Altaf
2021-06-04