Raphael Perrin
Raphael Perrin

Reputation: 63

Groovy merge YAML file wihout duplicates

I want to merge configuration file :

tool:
 jdk:
 - name: jdk8
   version: 8
 - name: jdk11
   version: 11

with file :

tool:
  jdk:
 - name: jdk11
   version: 11
 - name: jdk15
   version: 15

I expect as a result :

tool:
 jdk:
 - name: jdk8
   version: 8
 - name: jdk11
   version: 11
 - name: jdk15
   version: 15

Without duplicates. Am currently using the solution from @szymon-stepniak : https://e.printstacktrace.blog/how-to-merge-two-maps-in-groovy/#merge-maps-with-nested-maps

any idea on how I could avoid having duplicate ?

Thanks a lot

Upvotes: 0

Views: 711

Answers (1)

Matias Bjarland
Matias Bjarland

Reputation: 4482

The following code:

import groovy.yaml.*

def dataA = '''\
tool:
  jdk:
    - name: jdk8
      version: 8
    - name: jdk11
      version: 11
'''

def dataB = '''\
tool:
  jdk:
    - name: jdk11
      version: 11
    - name: jdk15
      version: 15
'''

def parser = new YamlSlurper()

def a = parser.parseText(dataA)
def b = parser.parseText(dataB)

def c = [tool: [jdk: (a.tool.jdk + b.tool.jdk).unique()]]

println "a: $a"
println "b: $b"
println "c: $c"

def builder = new YamlBuilder() 
builder c

println(builder)

when run, results in:

─➤ groovy solution.groovy
a: [tool:[jdk:[[name:jdk8, version:8], [name:jdk11, version:11]]]]
b: [tool:[jdk:[[name:jdk11, version:11], [name:jdk15, version:15]]]]
c: [tool:[jdk:[[name:jdk8, version:8], [name:jdk11, version:11], [name:jdk15, version:15]]]]
---
tool:
  jdk:
  - name: "jdk8"
    version: 8
  - name: "jdk11"
    version: 11
  - name: "jdk15"
    version: 15

This solution is not very generic as we hard code the x.tool.jdk path. An alternative would have been to write some kind of recursive merge function which can do this in a more generic manner.

Update after comments:

For the question in the comment you can do something like this:

def a = [tool: [jdk: [installations:
          [[name: 'latest-11', 
            properties: [[installSource: [installers:[[zip:[subdir:'jdk-11.999', url:'https://artifactory/OpenJDK11U_11.0.3_7.tar.gz']]]]]]]]]]] 

def b = [tool: [jdk: [installations:
          [[name: 'latest-11',  properties: [[installSource:[installers:[[zip:[subdir:'jdk-11.37', url:'https://artifactory/OpenJDK11U_11.0.3_7.tar.gz']]]]]]], 
           [name: 'jdk-11.0.3', properties: [[installSource:[installers:[[zip:[subdir:'jdk-11.3', url:'https://artifactory/OpenJDK11U_11.0.3_7.tar.gz']]]]]]]]]]]

def uniqueInstallations = (a.tool.jdk.installations + b.tool.jdk.installations).toUnique { x, y -> x.name <=> y.name }
def c = [tool: [jdk: [installations: uniqueInstallations]]]

uniqueInstallations.each { 
  println it
}

println "=="
println c

which prints:

➤ groovy solution2.groovy
[name:latest-11, properties:[[installSource:[installers:[[zip:[subdir:jdk-11.999, url:https://artifactory/OpenJDK11U_11.0.3_7.tar.gz]]]]]]]
[name:jdk-11.0.3, properties:[[installSource:[installers:[[zip:[subdir:jdk-11.3, url:https://artifactory/OpenJDK11U_11.0.3_7.tar.gz]]]]]]]
==
[tool:[jdk:[installations:[[name:latest-11, properties:[[installSource:[installers:[[zip:[subdir:jdk-11.999, url:https://artifactory/OpenJDK11U_11.0.3_7.tar.gz]]]]]]], [name:jdk-11.0.3, properties:[[installSource:[installers:[[zip:[subdir:jdk-11.3, url:https://artifactory/OpenJDK11U_11.0.3_7.tar.gz]]]]]]]]]]]

Upvotes: 0

Related Questions