0

Here is my code for merging 2 jsons into one... Is there a better way?

Expected behaviour is to get a 'big json' with sum of 'entry jsons' and no "type-XX" overlaps, and keeping the longest 'rc[ ]' list.

def json_src1 = '''
{
      "branch": {
                  "type-0.2": {
                      "version": "0.2",
                      "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                       }
              }
}
'''
def json_src2 = '''
{
      "branch": {
                  "type-0.3": {
                      "version": "0.3",
                      "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                      }
              }
}
'''

def concatenateJsons(json_src1, json_src2){
    def json = json_src1 + json_src2
    return json
}

To change strings to json objects:

json_src1 = new JsonSlurper().parseText(json_src1)
json_src2 = new JsonSlurper().parseText(json_src2)

To concatenate

json = concatenateJsons(json_src1, json_src2)
println JsonOutput.prettyPrint(JsonOutput.toJson(json))

Expected result:

{
"branch": {
           "type-0.2": {
           "version": "0.2",
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                       }

           "type-0.3": {
           "version": "0.3",
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                      }          
          }
}

P.S I am losing order of elements inside of Json after merge for no obvious reason : ("version": "0.3" moves to the bottom in type-03 {}:

Instead of:

{
"branch": {
           "type-0.2": {
           "version": "0.2",
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                       }

           "type-0.3": {
           "version": "0.3",
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                      }          
          }
}

I am getting

{
"branch": {
           "type-0.2": {
           "version": "0.2",
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]"
                       }

           "type-0.3": {
           "rc": "[17, 18, 19, 20, 21, 22, 23, 24]",
            "version": "0.3"
                      }          
          }
}
Wojtas.Zet
  • 636
  • 2
  • 10
  • 30

1 Answers1

1

the simplest thing you can do is to change the concatenateJsons function

def concatenateJsons(json_src1, json_src2){
    def json = [branch: json_src1.branch + json_src2.branch]
    return json
}

groovy not doing deep merge of parsed jsons it merges only root objects.

so, to merge content of branches just sum branch from each json

Note: if both json1 and json2 has the same type-X.Y then second overlaps content of first one.

daggett
  • 26,404
  • 3
  • 40
  • 56
  • I got to the same conclusion by trial and error. There is one side effect though. I am losing order of the merged elements. For instance `"version": "0.3"` and `"rc": "[17, 18, 19, 20, 21, 22, 23, 24]" ` got switched over. How could I ensure that `version` stays on top? – Wojtas.Zet Oct 18 '19 at 16:00
  • Could you modify example of source and output jsons to the question, so I could understand it better. – daggett Oct 18 '19 at 17:06
  • please see update in the question - for the example of switched order (`"version": "0.3"` goes to bottom) – Wojtas.Zet Oct 18 '19 at 19:36
  • there was issue in some old versions of groovy. normally it's not a problem because according to json specification order of keys in object has no meaning. if it's important for you - you could update groovy version or try other parser like gson... – daggett Oct 18 '19 at 20:03
  • I had troubles with JsonSlurper() and CPS errors in jenkins, so I have used JsonSlurperClassic()... which presumably is older? https://stackoverflow.com/questions/37864542/jenkins-pipeline-notserializableexception-groovy-json-internal-lazymap – Wojtas.Zet Oct 18 '19 at 20:42
  • Classic definitely has this issue. If you in pipeline - there is a native step to read json: https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readjson-read-json-from-files-in-the-workspace – daggett Oct 18 '19 at 21:24