我有一个项目,我会定期处理最多五层深度的 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"
我并不担心以这种方式精确格式化数据,只是寻找有关如何实际获取我需要的数据的提示。
好吧,我要尝试一些快速而肮脏的东西。 我认为你不知道自己在追求什么,所以这只是在墙上扔一些温泉,看看会粘上什么。
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 的解析。