如何使用jq对对象进行扁平化的逆运算?
How to get inverse operation of flatten for objects using jq?
通过另一个 SO 线程,我找到了如何 "flatten" JSON 使用 jq。我正在寻找如何做相反的事情,即 "unflatten" 它。
原 JSON 在层次结构中具有混合级别,例如:
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2" : {
"X1o2o1" : "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
如 https://jqplay.org/s/Eo6h_3V8PO 所示,为了与其他同事一起工作,我需要 "flatten" 该结构 () 使用
reduce (tostream|select(length==2)) as $i ({}; .[[$i[0][]|tostring]|join("_")] = $i[1] )
生产:
{
"X1_X1o1_X1o1o1": "abc",
"X1_X1o1_X1o1o2": "def",
"X1_X1o2_X1o2o1": "ghi",
"X1_X1o2_X1o2o2": "jkl",
"X1_X1o3": "mno",
"X2": "pqr"
}
我需要帮助的是如何使用 jq 将这样的输出 JSON 转换回原始形式?
我看到 split
仅适用于 tostring | split("_")
中的字符串。
任何指导我朝着正确方向前进的指针 and/or 示例将不胜感激。
根据您的示例输入,过滤器:
reduce to_entries[] as $kv ({}; setpath($kv.key|split("_"); $kv.value))
产生:
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
您可能想了解两种工具。第一个是名为 gron
的程序,它可以将 JSON 展平为有效的 JavaScript(可以展平为原始的 JSON)。它会把你的原件变成这样:
$ gron /tmp/foo.json
json = {};
json.X1 = {};
json.X1.X1o1 = {};
json.X1.X1o1.X1o1o1 = "abc";
json.X1.X1o1.X1o1o2 = "def";
json.X1.X1o2 = {};
json.X1.X1o2.X1o2o1 = "ghi";
json.X1.X1o2.X1o2o2 = "jkl";
json.X1.X1o3 = "mno";
json.X2 = "pqr";
并将其展开为 JSON:
$ gron /tmp/foo.json | gron -u
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
第二个是名为 jqg
的 Bash 脚本,使用 jq
可获得类似的结果;它的中间(扁平化)格式是有效的 JSON:
$ jqg . /tmp/foo.json
{
"X1.X1o1.X1o1o1": "abc",
"X1.X1o1.X1o1o2": "def",
"X1.X1o2.X1o2o1": "ghi",
"X1.X1o2.X1o2o2": "jkl",
"X1.X1o3": "mno",
"X2": "pqr"
}
展开为原来的样子:
$ jqg . /tmp/foo.json | jqg -u
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
注意:我是jqg
的作者。
通过另一个 SO 线程,我找到了如何 "flatten" JSON 使用 jq。我正在寻找如何做相反的事情,即 "unflatten" 它。
原 JSON 在层次结构中具有混合级别,例如:
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2" : {
"X1o2o1" : "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
如 https://jqplay.org/s/Eo6h_3V8PO 所示,为了与其他同事一起工作,我需要 "flatten" 该结构 () 使用
reduce (tostream|select(length==2)) as $i ({}; .[[$i[0][]|tostring]|join("_")] = $i[1] )
生产:
{
"X1_X1o1_X1o1o1": "abc",
"X1_X1o1_X1o1o2": "def",
"X1_X1o2_X1o2o1": "ghi",
"X1_X1o2_X1o2o2": "jkl",
"X1_X1o3": "mno",
"X2": "pqr"
}
我需要帮助的是如何使用 jq 将这样的输出 JSON 转换回原始形式?
我看到 split
仅适用于 tostring | split("_")
中的字符串。
任何指导我朝着正确方向前进的指针 and/or 示例将不胜感激。
根据您的示例输入,过滤器:
reduce to_entries[] as $kv ({}; setpath($kv.key|split("_"); $kv.value))
产生:
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
您可能想了解两种工具。第一个是名为 gron
的程序,它可以将 JSON 展平为有效的 JavaScript(可以展平为原始的 JSON)。它会把你的原件变成这样:
$ gron /tmp/foo.json
json = {};
json.X1 = {};
json.X1.X1o1 = {};
json.X1.X1o1.X1o1o1 = "abc";
json.X1.X1o1.X1o1o2 = "def";
json.X1.X1o2 = {};
json.X1.X1o2.X1o2o1 = "ghi";
json.X1.X1o2.X1o2o2 = "jkl";
json.X1.X1o3 = "mno";
json.X2 = "pqr";
并将其展开为 JSON:
$ gron /tmp/foo.json | gron -u
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
第二个是名为 jqg
的 Bash 脚本,使用 jq
可获得类似的结果;它的中间(扁平化)格式是有效的 JSON:
$ jqg . /tmp/foo.json
{
"X1.X1o1.X1o1o1": "abc",
"X1.X1o1.X1o1o2": "def",
"X1.X1o2.X1o2o1": "ghi",
"X1.X1o2.X1o2o2": "jkl",
"X1.X1o3": "mno",
"X2": "pqr"
}
展开为原来的样子:
$ jqg . /tmp/foo.json | jqg -u
{
"X1": {
"X1o1": {
"X1o1o1": "abc",
"X1o1o2": "def"
},
"X1o2": {
"X1o2o1": "ghi",
"X1o2o2": "jkl"
},
"X1o3": "mno"
},
"X2": "pqr"
}
注意:我是jqg
的作者。