Groovy JSONSlurper - 如何访问多个级别的对象/数组?

问题描述 投票:0回答:1

我有一个项目,我会定期处理最多五层深度的 JSON 文件。元素始终相同,但每个级别可能作为数组或单个对象出现。

迭代这些的最佳方法是什么?我原本打算尝试使用 JSONPath 进行循环,但我只是在学习地图并想知道这是否会更容易/更干净?

默认情况下,我只获得一个键,并且它用于根元素。有没有办法为其他级别添加键?

下面是我正在使用的 JSON 的“简化”。所有 HL#Type 都可以是数组。有时会有 HL5。

{
"HL1": {
    "HL1Type": [
        {
            "Item1": "123",
            "Item2": "abc",
            "to_HL2": {
                "HL2Type": {
                    "ActualDeliveryQuantity": "6000.000",
                    "DeliveryQuantityUnit": "KP",
                    "to_HL3": {
                        "HL3Type": {
                            "HandlingUnitHeight": "10.000",
                            "HandlingUnitLength": "20.000",
                            "to_HL4": {
                                "HL4Type": {
                                    "MATERIAL": "ABC123",
                                    "to_HL5": ""
                                }
                            },
                            "UnitOfMeasureDimension": ""
                        }
                    }
                }
            }
        },
        {
            "Item1": "456",
            "Item2": "def",
            "to_HL2": {
                "HL2Type": {
                    "ActualDeliveryQuantity": "7000.000",
                    "DeliveryQuantityUnit": "KP",
                    "to_HL3": {
                        "HL3Type": [
                            {
                                "HandlingUnitHeight": "10.000",
                                "HandlingUnitLength": "20.000",
                                "to_HL4": {
                                    "HL4Type": {
                                        "MATERIAL": "DEF456",
                                        "to_HL5": ""
                                    }
                                },
                                "UnitOfMeasureDimension": ""
                            },
                            {
                                "HandlingUnitHeight": "20.000",
                                "HandlingUnitLength": "30.000",
                                "to_HL4": {
                                    "HL4Type": {
                                        "MATERIAL": "GHI789",
                                        "to_HL5": ""
                                    }
                                },
                                "UnitOfMeasureDimension": ""
                            }
                        ]
                    }
                }
            }
        }
    ]
}

我是地图新手,所以到目前为止我所掌握的都是非常基础的。

import java.util.Properties;
import java.io.InputStream;
import groovy.json.JsonSlurper;
import groovy.json.JsonOutput;

def inputFile = new File("C:\\ExampleJSON.json")
def InputJSON = new JsonSlurper().parseFile(inputFile, 'UTF-8')
InputJSON = InputJSON.HL1.HL1Type

InputJSON.eachWithIndex{ Item, idx -> 
    println "$idx: $Item" }

InputJSON.to_HL2.HL2Type.eachWithIndex{ Item, idx -> 
    println "$idx: $Item" }

我可以显示所有内容,但我正在寻找一种迭代方法,我可以得到类似的内容:

"123, abc, 6000, KP, 10, 20, ABC123"
"456, def, 7000, KP, 10, 20, DEF456"
"456, def, 7000, KP, 20, 30, GHI789"

我并不担心以这种方式精确格式化数据,只是寻找有关如何实际获取我需要的数据的提示。

groovy jsonslurper
1个回答
0
投票

好吧,我要尝试一些快速而肮脏的东西。 我认为你不知道自己在追求什么,所以这只是在墙上扔一些温泉,看看会粘上什么。

import java.util.Properties;
import java.io.InputStream;
import groovy.json.JsonSlurper;
import groovy.json.JsonOutput;

def input = new File("C:\\ExampleJSON.json")
def json = new JsonSlurper().parseFile(input, 'UTF-8')

List<Map<String,Object>> items = json.HL1.HL1Type.collect { item ->
   [
      Item1: item.Item1,
      Item2: item.Item2,
      ActualDeliveryQuantity: item.to_HL2.HL2Type.ActualDeliveryQuantity,
      DeliveryQuantityUnit: item.to_HL2.HL2Type.DeliveryQuantityUnit,
      HandlingUnitHeight: item.to_HL2.HL2Type.to_HL3.HL3Type.HandlingUnitHeight,
      HandlingUnitLength: item.to_HL2.HL2Type.to_HL3.HL3Type.HandlingUnitLength,
      Material: item.to_HL2.HL2Type.to_HL3.HL3Type.to_HL4.HL4Type.MATERIAL
   ]      
}

items.each { row ->
   println( "${row.Item1} ${row.Item2} ${row.ActualDeliveryQuantity} ${row.DeliveryQuantityUnit} ${row.HandlingUnitHeight} ${row.HandlingUnitLength} ${row.Material}" )
}

您可以通过将 HL2Type 和 HL3Type 抓取到本地变量中来简化此内容的阅读,这使得嵌套部分更易于阅读。

List<Map<String,Object>> items = json.HL1.HL1Type.collect { item ->
   def hl2Type = item.to_HL2.HL2Type
   def hl3Type = item.to_HL2.HL2Type.to_HL3.HL3Type
   def hl4Type = item.to_HL2.HL2Type.to_HL3.HL3Type.to_HL4.HL4Type
   [
      Item1: item.Item1,
      Item2: item.Item2,
      ActualDeliveryQuantity: hl2Type.ActualDeliveryQuantity,
      DeliveryQuantityUnit: hl2Type.DeliveryQuantityUnit,
      HandlingUnitHeight: hl3Type.HandlingUnitHeight,
      HandlingUnitLength: hl3Type.HandlingUnitLength,
      Material: hl4Type.MATERIAL
   ]      
}

但最重要的是,它所做的是迭代 JSON 数组并返回 Map 对象列表,这些对象是 JSON 对象的扁平化表示。 Map 的键与数据来源的字段名称相匹配,值就是数据。

这不是一个通用的 JSON 解析器,而只是一个框架,供您在不同的路径中滑动到对象以生成简单的脚本。 请注意,这种方式将视觉表示与处理分开。 迭代提取的映射集可以呈现为您希望的任何格式,而不影响 JSON 的解析。

© www.soinside.com 2019 - 2024. All rights reserved.