【问题标题】:Groovy collect nested elements along with outer elementGroovy 收集嵌套元素和外部元素
【发布时间】:2019-04-07 14:27:34
【问题描述】:

使用 Groovy,要求是收集地图的嵌套元素值及其顶级元素值。

不确定是否需要递归方法。

示例 JSON

{
"items": [
      {
      "attribute": "Type",
      "options":       
      [
                  {
            "label": "Type1",
            "value": "1"
         },
                  {
            "label": "Type2",
            "value": "2"
         }

      ]
   },
      {
      "attribute": "Size",
      "options":       [
                  {
            "label": "SizeA",
            "value": "A"
         },
                  {
            "label": "SizeB",
            "value": "B"
         }
      ]
   }
]
}

收集后的预期输出

[
{attribute=Type,label=Type1,value=1},
{attribute=Type,label=Type2,value=2},
{attribute=Size,label=SizeA,value=A},
{attribute=Size,label=SizeB,value=B}
]

【问题讨论】:

    标签: json groovy nested collect


    【解决方案1】:

    您可以使用collectMany 组合通过collect 方法获得的多个options 列表来解决此问题。

    见下面sn-p的代码:

    def input = """
    {
      "items": [
        {
          "attribute": "Type",
          "options": [
             {
               "label": "Type1",
               "value": "1"
             },
             {
               "label": "Type2",
               "value": "2"
             }
          ]
       },
       {
         "attribute": "Size",
         "options": [
             {
                "label": "SizeA",
                "value": "A"
             },
             {
                "label": "SizeB",
                "value": "B"
             }
         ]
      } ]
    }"""
    
    def json = new groovy.json.JsonSlurper().parseText(input)
    
    /* collectMany directly flatten the two sublists 
     * [ [ [ type1 ], [ type2 ] ], [ [ sizeA ], [ sizeB ] ] ]
     * into
     * [ [type1], [type2], [sizeA], [sizeB] ]
     */
    def result = json.items.collectMany { item ->
        // collect returns a list of N (in this example, N=2) elements 
        // [ [ attribute1: ..., label1: ..., value1: ... ],
        //   [ attribute2: ..., label2: ..., value2: ... ] ]
        item.options.collect { option ->
            // return in [ attribute: ..., label: ..., value: ... ]
            [ attribute: item.attribute ] + option
        }
    }
    
    assert result == [
        [ attribute: "Type", label: "Type1", value: "1" ],
        [ attribute: "Type", label: "Type2", value: "2" ],
        [ attribute: "Size", label: "SizeA", value: "A" ],
        [ attribute: "Size", label: "SizeB", value: "B" ],
    ]
    

    【讨论】:

      【解决方案2】:

      感谢朱塞佩! 我已经用一种不那么时髦的方法解决了这个问题:

      def result  = [];//Create new list with top-level element and nested elements
      json.items.each {item ->
          result.addAll(item.options.collect{ option ->
              [attribute: /"${item?.attribute?:''}"/, label: /"${option?.label?:''}"/, value: /"${option?.value?:''}"/ ]
          })
      };
      

      【讨论】:

      • 很高兴看到您找到了适合您的代码库的东西。请注意,使用 /"${item?.attribute?:''}"/ 您正在更改 attribute 用双引号 "value" 包裹它。因此,在 json 中,您将获得 "attribute":"\"Type\"" 而不是预期的 "attribute":"Type"。要修复它,只需留下 item?.attribute ?: '' 代替 /"${item?.attribute?:''}"/
      猜你喜欢
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      相关资源
      最近更新 更多