我想“转置”(不确定这个词是否正确)JSON 元素。
例如,我有一个这样的 JSON 文件:
{
"name": {
"0": "fred",
"1": "barney"
},
"loudness": {
"0": "extreme",
"1": "not so loud"
}
}
...我想生成一个像这样的 JSON 数组:
[
{
"name": "fred",
"loudness": "extreme"
},
{
"name": "barney",
"loudness": "not so loud"
}
]
我的原始 JSON 具有比“名称”和“响度”更多的第一级元素,以及更多的名称、特征等。
对于这个简单的示例,我可以像这样完全指定转换:
$ echo '{"name":{"0":"fred","1":"barney"},"loudness":{"0":"extreme","1":"not so loud"}}'| \
> jq '[{"name":.name."0", "loudness":.loudness."0"},{"name":.name."1", "loudness":.loudness."1"}]'
[
{
"name": "fred",
"loudness": "extreme"
},
{
"name": "barney",
"loudness": "not so loud"
}
]
...但这对于原始 JSON 是不可行的。
对于更大的 JSON 文件,jq 如何在与 key 无关的情况下创建所需的输出?
最佳答案
是的,transpose
是一个合适的词,如下所示。
下面的通用帮助函数提供了一个简单的解决方案,它完全不知道键名,包括封闭对象和内部对象:
# Input: an array of values
def objectify($keys):
. as $in | reduce range(0;length) as $i ({}; .[$keys[$i]] = $in[$i]);
假设内键顺序的一致性
假设内部对象中的键名以一致的顺序给出,现在可以得到如下解决方案:
keys_unsorted as $keys
| [.[] | [.[]]] | transpose
| map(objectify($keys))
不假设内键顺序的一致性
如果不能假定内部键的顺序是一致的,那么一种方法是对它们进行排序,例如使用这个通用辅助函数:
def reorder($keys):
. as $in | reduce $keys[] as $k ({}; .[$k] = $in[$k]);
或者如果你更喜欢 reduce-free def:
def reorder($keys): [$keys[] as $k | {($k): .[$k]}] | add;
上面的“主”程序可以修改如下:
keys_unsorted as $keys
| (.[$keys[0]]|keys_unsorted) as $inner
| map_values(reorder($inner))
| [.[] | [.[]]] | transpose
| map(objectify($keys))
警告
上述解决方案仅考虑第一个内部对象中的键名。
关于json - "Transpose"/"Rotate"/"Flip"JSON 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64455986/