从 JSON 子对象数组中提取 属性 到列中以逗号分隔的值
Extract property from JSON child object array into a comma-delimited value in a column
我有一个固定深度的分层 JSON 对象数组,我想使用 PowerQuery 将其作为 table 导入 Excel.
这是一个示例,代表了我能够成功达到的程度:
let
json = "[
{
""t"": {
""a"": {
""p"": [
{
""id"": ""5z1V"",
""name"": ""p-First"",
""type"": ""p""
}
],
""id"": ""2aXp"",
""name"": ""a-un""
},
""p"": [
{
""id"": ""5z1V"",
""name"": ""p-First"",
""type"": ""p""
},
{
""id"": ""3BDN"",
""name"": ""p-Second"",
""type"": ""p""
}
],
""id"": ""6Goh"",
""name"": ""t-Primary""
}
},
{
""t"": {
""a"": {
""p"": [
{
""href"": ""https://api.example.com/v1/p/1Gxk"",
""id"": ""1Gxk"",
""name"": ""p-Third"",
""type"": ""p"",
""uri"": ""p:1Gxk""
}
],
""id"": ""3CKV"",
""name"": ""a-deux""
},
""p"": [
{
""id"": ""1Gxk"",
""name"": ""p-Third"",
""type"": ""p""
}
],
""id"": ""0lLd"",
""name"": ""t-Secondary""
}
}
]",
Source = Json.Document(json),
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"t"}, {"t"}),
#"Expanded t" = Table.ExpandRecordColumn(#"Expanded Column1", "t", {"a", "p", "id", "name"}, {"t.a", "t.p", "t.id", "t.name"}),
#"Expanded t.a" = Table.ExpandRecordColumn(#"Expanded t", "t.a", {"p", "id", "name"}, {"t.a.p", "t.a.id", "t.a.name"})
in
#"Expanded t.a"
然而,这只会给我一个 table 这样的:
t.a.p
t.a.id
t.a.name
t.p
t.id
t.name
[List]
2aXp
a-un
[List]
6Goh
t-Primary
[List]
3CKV
a-deux
[List]
0lLd
t-Secondary
我想要的是将那些 [List] 值扩展为来自“p”对象的“名称”属性 的逗号分隔值(所有“p”对象都是同一类型, 虽然有些“p”对象是“a”对象的子对象,有些“p”对象是“t”对象的子对象。
当我尝试扩展 t.a.p
列或 t.p
列时,我有两个选择:
- 扩展到新行:捕获所有“p”属性并创建新行,当存在多个“p”对象时,这是一个问题。我只想保留“p”对象的“名称”属性。
- Expant Values...:为每一行生成错误:“Expression.Error:我们无法将 Record 类型的值转换为 Text 类型。”。查询中有问题的行是:
= Table.TransformColumns(#"Expanded t.a", {"t.a.p", each Text.Combine(List.Transform(_, Text.From), ","), type text})
最终结果应该是这样的:
t.a.p
t.a.id
t.a.name
t.p
t.id
t.name
p-First
2aXp
a-un
p-First, p-Second
6Goh
t-Primary
p-Third
3CKV
a-deux
p-Third
0lLd
t-Secondary
如果有帮助,每个“a”对象中总是有一个或多个“p”对象,每个“t”对象中总是有一个或多个“p”对象。 “p”对象无论在“a”还是“t”对象中都具有相同的模式。
你非常接近。问题是这些列是记录列表,您想要专门提取 name
记录。因此,您可以使用函数 each [name]
.
,而不是对记录没有意义的 Text.From
= Table.TransformColumns(
#"Expanded t.a",
{"t.p", each Text.Combine(List.Transform(_, each [name]), ", "), type text}
)
each
语法在这里可能有点混乱,所以如果您愿意,可以使用带有 () =>
的函数式语法来编写它。即
= Table.TransformColumns(
#"Expanded t.a",
{"t.p", (C) => Text.Combine(List.Transform(C, (R) => R[name]), ", "), type text}
)
我选择 C
作为列的变量名称,并选择 R
作为记录。
我有一个固定深度的分层 JSON 对象数组,我想使用 PowerQuery 将其作为 table 导入 Excel.
这是一个示例,代表了我能够成功达到的程度:
let
json = "[
{
""t"": {
""a"": {
""p"": [
{
""id"": ""5z1V"",
""name"": ""p-First"",
""type"": ""p""
}
],
""id"": ""2aXp"",
""name"": ""a-un""
},
""p"": [
{
""id"": ""5z1V"",
""name"": ""p-First"",
""type"": ""p""
},
{
""id"": ""3BDN"",
""name"": ""p-Second"",
""type"": ""p""
}
],
""id"": ""6Goh"",
""name"": ""t-Primary""
}
},
{
""t"": {
""a"": {
""p"": [
{
""href"": ""https://api.example.com/v1/p/1Gxk"",
""id"": ""1Gxk"",
""name"": ""p-Third"",
""type"": ""p"",
""uri"": ""p:1Gxk""
}
],
""id"": ""3CKV"",
""name"": ""a-deux""
},
""p"": [
{
""id"": ""1Gxk"",
""name"": ""p-Third"",
""type"": ""p""
}
],
""id"": ""0lLd"",
""name"": ""t-Secondary""
}
}
]",
Source = Json.Document(json),
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"t"}, {"t"}),
#"Expanded t" = Table.ExpandRecordColumn(#"Expanded Column1", "t", {"a", "p", "id", "name"}, {"t.a", "t.p", "t.id", "t.name"}),
#"Expanded t.a" = Table.ExpandRecordColumn(#"Expanded t", "t.a", {"p", "id", "name"}, {"t.a.p", "t.a.id", "t.a.name"})
in
#"Expanded t.a"
然而,这只会给我一个 table 这样的:
t.a.p |
t.a.id |
t.a.name |
t.p |
t.id |
t.name |
---|---|---|---|---|---|
[List] |
2aXp |
a-un |
[List] |
6Goh |
t-Primary |
[List] |
3CKV |
a-deux |
[List] |
0lLd |
t-Secondary |
我想要的是将那些 [List] 值扩展为来自“p”对象的“名称”属性 的逗号分隔值(所有“p”对象都是同一类型, 虽然有些“p”对象是“a”对象的子对象,有些“p”对象是“t”对象的子对象。
当我尝试扩展 t.a.p
列或 t.p
列时,我有两个选择:
- 扩展到新行:捕获所有“p”属性并创建新行,当存在多个“p”对象时,这是一个问题。我只想保留“p”对象的“名称”属性。
- Expant Values...:为每一行生成错误:“Expression.Error:我们无法将 Record 类型的值转换为 Text 类型。”。查询中有问题的行是:
= Table.TransformColumns(#"Expanded t.a", {"t.a.p", each Text.Combine(List.Transform(_, Text.From), ","), type text})
最终结果应该是这样的:
t.a.p |
t.a.id |
t.a.name |
t.p |
t.id |
t.name |
---|---|---|---|---|---|
p-First |
2aXp |
a-un |
p-First, p-Second |
6Goh |
t-Primary |
p-Third |
3CKV |
a-deux |
p-Third |
0lLd |
t-Secondary |
如果有帮助,每个“a”对象中总是有一个或多个“p”对象,每个“t”对象中总是有一个或多个“p”对象。 “p”对象无论在“a”还是“t”对象中都具有相同的模式。
你非常接近。问题是这些列是记录列表,您想要专门提取 name
记录。因此,您可以使用函数 each [name]
.
Text.From
= Table.TransformColumns(
#"Expanded t.a",
{"t.p", each Text.Combine(List.Transform(_, each [name]), ", "), type text}
)
each
语法在这里可能有点混乱,所以如果您愿意,可以使用带有 () =>
的函数式语法来编写它。即
= Table.TransformColumns(
#"Expanded t.a",
{"t.p", (C) => Text.Combine(List.Transform(C, (R) => R[name]), ", "), type text}
)
我选择 C
作为列的变量名称,并选择 R
作为记录。