31

I have to create this JSON file in Groovy. I have try many things (JsonOutput.toJson() / JsonSlurper.parseText()) unsuccessfully.

{
   "attachments":[
      {
         "fallback":"New open task [Urgent]: <http://url_to_task|Test out Slack message attachments>",
         "pretext":"New open task [Urgent]: <http://url_to_task|Test out Slack message attachments>",
         "color":"#D00000",
         "fields":[
            {
               "title":"Notes",
               "value":"This is much easier than I thought it would be.",
               "short":false
            }
         ]
      }
   ]
}

This is for posting a Jenkins build message to Slack.

Marco Roy
  • 4,004
  • 7
  • 34
  • 50
Mr_DeLeTeD
  • 825
  • 1
  • 6
  • 18
  • in title of question you asking about parsing, and in question itself you asking about creating json file. could you please clarify what you want/try to do. – daggett Jun 23 '17 at 10:12
  • @daggett i would like to create those JSON object into a groovy variable. – Mr_DeLeTeD Jun 23 '17 at 14:38

4 Answers4

76

JSON is a format that uses human-readable text to transmit data objects consisting of attribute–value pairs and array data types. So, in general json is a formatted text.

In groovy json object is just a sequence of maps/arrays.

parsing json using JsonSlurperClassic

//use JsonSlurperClassic because it produces HashMap that could be serialized by pipeline
import groovy.json.JsonSlurperClassic

node{
    def json = readFile(file:'message2.json')
    def data = new JsonSlurperClassic().parseText(json)
    echo "color: ${data.attachments[0].color}"
}

parsing json using pipeline

node{
    def data = readJSON file:'message2.json'
    echo "color: ${data.attachments[0].color}"
}

building json from code and write it to file

import groovy.json.JsonOutput
node{
    //to create json declare a sequence of maps/arrays in groovy
    //here is the data according to your sample
    def data = [
        attachments:[
            [
                fallback: "New open task [Urgent]: <http://url_to_task|Test out Slack message attachments>",
                pretext : "New open task [Urgent]: <http://url_to_task|Test out Slack message attachments>",
                color   : "#D00000",
                fields  :[
                    [
                        title: "Notes",
                        value: "This is much easier than I thought it would be.",
                        short: false
                    ]
                ]
            ]
        ]
    ]
    //two alternatives to write

    //native pipeline step:
    writeJSON(file: 'message1.json', json: data)

    //but if writeJSON not supported by your version:
    //convert maps/arrays to json formatted string
    def json = JsonOutput.toJson(data)
    //if you need pretty print (multiline) json
    json = JsonOutput.prettyPrint(json)

    //put string into the file:
    writeFile(file:'message2.json', text: json)

}
hisener
  • 1,431
  • 1
  • 17
  • 23
daggett
  • 26,404
  • 3
  • 40
  • 56
  • 3
    I'm trying to do this. I get "ERROR: org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new groovy.json.JsonSlurperClassic" What am I missing? – Chris F Jun 08 '18 at 17:08
  • 1
    https://stackoverflow.com/questions/38276341/jenkins-ci-pipeline-scripts-not-permitted-to-use-method-groovy-lang-groovyobject – daggett Jun 09 '18 at 08:16
  • This doesn't work for me in the latest version of jenkins (2.138.3). I get an issue on the writeJSON step: `WriteJSONStep(file: String, json: JSON{}, pretty?: int): java.lang.UnsupportedOperationException: must specify $class with an implementation of interface net.sf.json.JSON`More context here: https://stackoverflow.com/questions/53337109/jenkinsfile-pipeline-construct-json-object-and-write-to-file – David Nov 16 '18 at 14:31
  • @DavidGoate, in this case don't use `writeFile`, but the last three commands in code: `JsonOutput.toJson`, `JsonOutput.prettyPrint`, `writeFile`. – daggett Nov 16 '18 at 15:12
  • I solved it in the end, but thanks for your input. I needed to add `as String` to my map properties. See https://stackoverflow.com/questions/53337109/jenkinsfile-pipeline-construct-json-object-and-write-to-file for more. I don't fully understand why, hence i've also asked https://stackoverflow.com/questions/53340121/adding-a-string-to-a-groovy-map-with-a-variable-using-interpolation – David Nov 16 '18 at 18:36
  • 1
    Thank you for the information about JsonSlurperClassic. I tried JsonSlurper, but it causes NotSerializableException if "new" is called more than once, even despite NonCPS annotation. – Alexander Samoylov Apr 22 '20 at 12:16
23

Found this question while I was trying to do something (I believed) should be simple to do, but wasn't addressed by the other answer. If you already have the JSON loaded as a string inside a variable, how do you convert it to a native object? Obviously you could do new JsonSlurperClassic().parseText(json) as the other answer suggests, but there is a native way in Jenkins to do this:

node () {
  def myJson = '{"version":"1.0.0"}';
  def myObject = readJSON text: myJson;
  echo myObject.version;
}

Hope this helps someone.

Edit: As explained in the comments "native" isn't quite accurate.

mrfred
  • 613
  • 4
  • 15
  • 9
    Good call, though this is not quite native, it requires the [pipeline utility steps plugin](https://plugins.jenkins.io/pipeline-utility-steps). An excellent plugin to make use of. [Full docs here](https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/) – Nigel Kirby Jan 22 '18 at 23:49
  • 1
    if we have a string '[ {"version":"1.0.0"} , {"version":"2.0.0"}]' how to read the array ? – sirineBEJI Jun 26 '18 at 16:27
  • You will need _Pipeline Utility Steps_ plugin as mentioned [here](https://stackoverflow.com/a/46852563/234110) – Anand Rockzz Jul 10 '18 at 23:49
  • this addresses the opposite of the OPs question: how to go from object to json string – 333kenshin Nov 04 '20 at 12:03
2

If you are stucked on an installation using sandboxes and Jenkins Script Security plugin with no possibility to add whitelisted classes/methods, the only way I found is the following :

def slackSendOnRestrictedContext(params) {

    if (params.attachments != null) {
        /* Soooo ugly but no other choice with restrictions of
           Jenkins Script Pipeline Security plugin ^^ */
        def paramsAsJson = JsonOutput.toJson(params)
        def paramsAsJsonFromReadJson = readJSON text: paramsAsJson
        params.attachments = paramsAsJsonFromReadJson.attachments.toString()
    }

    slackSend (params)
}
Azat
  • 2,275
  • 1
  • 28
  • 32
Nicolas Vuillamy
  • 564
  • 7
  • 14
-1

This will return value of the "version" from the jsonFile file:

def getVersion(jsonFile){

  def fileContent = readFile "${jsonFile}"
  Map jsonContent = (Map) new JsonSlurper().parseText(fileContent)
  version = jsonContent.get("version")

  return version

}