groovy YAML 删除几行

groovy YAML delete few lines

使用 groovy yaml 解析器我需要删除以下行并写入文件。

要删除的行。

 - name: hostname
    required: true
    secure: false
    valueExposed: true

当我尝试加载要映射的 yaml 数据时。它失败了 'org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ' 异常。

我正在寻求帮助。如何加载此 yaml 数据并从中删除 4 行。

import org.yaml.snakeyaml.DumperOptions
import org.yaml.snakeyaml.Yaml

class Test {
    def static main(args) {

        DumperOptions options = new DumperOptions()
        options.setPrettyFlow(true)
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK)
        Yaml yaml = new Yaml(options)
        def Map map = (Map) yaml.load(data)
        println yaml.dump(map)
    }


    def static String data = '''
- description: checkc the disk spacce
  executionEnabled: true
  loglevel: INFO
  name: disk spacce
  options:
  - description: file system name
    name: filesystem
    required: true
  - name: hostname
    required: true
    secure: false
    valueExposed: true
  scheduleEnabled: true
  sequence:
    commands:
    - exec: df -h
    keepgoing: false
'''
}

如果您仔细查看异常消息,您会注意到您正在尝试将 List 转换为 Map,这会引发 ClassCastException。您肯定需要阅读和理解 YAML 结构,因为您在之前的 .

中犯了同样的错误

所以要将数据加载到列表中: List list = (List) yaml.load(data)

现在,如果您确定 yaml 数据的结构,那么您可以使用 list.first().options.remove(1).

以丑陋但直接的方式删除数据

或者您可以遍历数据并找到需要删除的数据,然后将其删除。

static Map dataToBeRemoved = [
        name        : 'hostname',
        required    : true,
        secure      : false,
        valueExposed: true
]

public static findAndRemoveMap(List list) {
    Object o
    ListIterator iterator = list.listIterator()
    while (iterator.hasNext()) {
        o = iterator.next()
        if (o instanceof Map) {
            if (compareJsonObjects(dataToBeRemoved, o)) {
                iterator.remove()
            } else {
                o.findAll { it.value instanceof List }.each {
                    findAndRemoveMap(it.value)
                }
            }
        } else if (o instanceof List) {
            findAndRemoveMap(o)
        }
    }
}

compareJsonObjects是比较两个map和return是否相等的方法。您可以创建自己的实现,也可以使用外部库,例如 skyscreamer 中的 jsonassert。使用 jsonassertcompareJsonObjects 的实现将是:

public static boolean compareJsonObjects(Map<String, Object> obj_1, Map<String, Object> obj_2) {
    String one = new groovy.json.JsonBuilder(obj_1).toPrettyString()
    String two = new groovy.json.JsonBuilder(obj_2).toPrettyString()

    JSONCompareResult r = JSONCompare.compareJSON(one, two, JSONCompareMode.NON_EXTENSIBLE)
    return r.passed()
}

正如@sandeep-poonia 已经提到的,转换异常是因为 Map 数据类型,您可以参考此代码来解析和删除这些行。

static Map dataToBeRemoved = [
        name        : 'hostname',
        required    : true,
        secure      : false,
        valueExposed: true
]

static def removeEntries
removeEntries = {def yaml ->
   if(yaml.getClass() == ArrayList){
      yaml = yaml.collect {
         removeEntries(it)
      }
      yaml = yaml.findAll{it} // remove empty items (list or map) from list. 
   } else if(yaml.getClass() == LinkedHashMap){
      if(!(dataToBeRemoved - yaml)){
         yaml = yaml - dataToBeRemoved
      }
      yaml.each{
         yaml[it.key] = removeEntries(it.value)
      }
   }
   yaml
}
   def static main(args){
        DumperOptions options = new DumperOptions()
        options.setPrettyFlow(true)
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK)
        Yaml yaml = new Yaml(options)
        List yamlData = yaml.load(data)
        yamlData = removeEntries(yamlData)
        println yaml.dump(yamlData)
    }