使用jq在JSON结构中更深层地转换键的名称
我有以下建议:使用jq在JSON结构中更深层地转换键的名称,json,jq,Json,Jq,我有以下建议: { "vertices": [ { "__cp": "foo", "__type": "metric", "__eid": "foobar", "name": "Undertow Metrics~Sessions Created", "_id": 45056, "_type": "vertex" }, ... ] "edges": [ ... 我希望实现这种格式: {
{
"vertices": [
{
"__cp": "foo",
"__type": "metric",
"__eid": "foobar",
"name": "Undertow Metrics~Sessions Created",
"_id": 45056,
"_type": "vertex"
},
...
]
"edges": [
...
我希望实现这种格式:
{
"nodes": [
{
"cp": "foo",
"type": "metric",
"label": "metric: Undertow Metrics~Sessions Created",
"name": "Undertow Metrics~Sessions Created",
"id": 45056
},
...
]
"edges": [
...
到目前为止,我能够创建以下表达式:
jq '{nodes: .vertices} | del(.nodes[]."_type", .nodes[]."__eid")'
例如,将“顶点”重命名为“节点”并删除“\u type”和“\u eid”,如何重命名JSON中嵌套得更深的键?如果与\u entriesfilter一起使用,可以更改对象属性的名称。这会将对象转换为键/值对数组,并对键/值对应用筛选器,然后再转换回对象。因此,您只需要将这些对象的键更新为新名称 根据您使用的jq版本,下一部分可能会比较棘手。直到JQ1.5才引入字符串替换。如果可用,您可以执行以下操作:
{
nodes: .vertices | map(with_entries(
.key |= sub("^_+"; "")
)),
edges
}
否则,如果您使用的是JQ1.4,则必须手动删除它们。递归函数可以帮助实现这一点,因为下划线的数量不同
def ltrimall(str): str as $str |
if startswith($str)
then ltrimstr($str) | ltrimall(str)
else .
end;
{
nodes: .vertices | map(with_entries(
.key |= ltrimall("_")
)),
edges
}
如果与_entriesfilter一起使用,则可以更改对象特性的名称。这会将对象转换为键/值对数组,并对键/值对应用筛选器,然后再转换回对象。因此,您只需要将这些对象的键更新为新名称 根据您使用的jq版本,下一部分可能会比较棘手。直到JQ1.5才引入字符串替换。如果可用,您可以执行以下操作:
{
nodes: .vertices | map(with_entries(
.key |= sub("^_+"; "")
)),
edges
}
否则,如果您使用的是JQ1.4,则必须手动删除它们。递归函数可以帮助实现这一点,因为下划线的数量不同
def ltrimall(str): str as $str |
if startswith($str)
then ltrimstr($str) | ltrimall(str)
else .
end;
{
nodes: .vertices | map(with_entries(
.key |= ltrimall("_")
)),
edges
}
以下程序适用于JQ1.4或JQ1.5。 它使用walk/1删除任何键的前导下划线,无论它出现在输入JSON中的何处 这里提供的ltrim版本使用recurse/1以提高效率和可移植性,但也可以使用任何合适的替代品
def ltrim(c):
reduce recurse( if .[0:1] == c then .[1:] else null end) as $x
(null; $x);
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
.vertices = .nodes
| del(.nodes)
| (.vertices |= walk(
if type == "object"
then with_entries( .key |= ltrim("_") )
else .
end ))
以下程序适用于JQ1.4或JQ1.5。 它使用walk/1删除任何键的前导下划线,无论它出现在输入JSON中的何处 这里提供的ltrim版本使用recurse/1以提高效率和可移植性,但也可以使用任何合适的替代品
def ltrim(c):
reduce recurse( if .[0:1] == c then .[1:] else null end) as $x
(null; $x);
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
.vertices = .nodes
| del(.nodes)
| (.vertices |= walk(
if type == "object"
then with_entries( .key |= ltrim("_") )
else .
end ))
从您的示例数据来看,您似乎打算进行许多小操作,因此我将把事情分为以下几个阶段:
.nodes = .vertices # \ first take care of renaming
| del(.vertices) # / .vertices to .nodes
| .nodes = [
.nodes[] # \ then scan each node
| . as $n # /
| del(._type, .__eid) # \ whatever key-specific tweaks like
| .label = "metric: \(.name)" # / calculating .label you want can go here
| reduce keys[] as $k ( # \
{}; # | final reduce to handle renaming
.[$k | sub("^_+";"")] = $n[$k] # | any keys that start with _
) # /
]
从您的示例数据来看,您似乎打算进行许多小操作,因此我将把事情分为以下几个阶段:
.nodes = .vertices # \ first take care of renaming
| del(.vertices) # / .vertices to .nodes
| .nodes = [
.nodes[] # \ then scan each node
| . as $n # /
| del(._type, .__eid) # \ whatever key-specific tweaks like
| .label = "metric: \(.name)" # / calculating .label you want can go here
| reduce keys[] as $k ( # \
{}; # | final reduce to handle renaming
.[$k | sub("^_+";"")] = $n[$k] # | any keys that start with _
) # /
]