我想知道是否有一种方法可以使用jq重新组织对象的字段。
我的意思是,假设
{
"prop1": 1,
"prop2": {
"nested": 0
},
"prop3": true
}
我想获取这个
{
"prop1": 1,
"prop3": true,
"prop2": {
"nested": 0
}
}
我想要选择字段的顺序(不考虑字段类型或字母顺序,只根据我的选择 :))。
谢谢!
[以下是2015年8月发布答案的更新内容!]
对于 jq 版本1.4及以上的版本,显式指定键的顺序最简单的方法是使用
{foo,bar,...}
来指定对象。例如,如果输入文件 input.json 中有问题中显示的 JSON,则可以执行以下操作:
jq -Mc '{prop1, prop3, prop2}' input.json
生成:
{"prop1":1,"prop3":true,"prop2":{"nested":0}}
def orderKeys(keys):
. as $in
| reduce keys[] as $key ({}; . + { ($key): $in[$key] });
# Example:
orderKeys( ["prop1", "prop3", "prop2"] )
将上述内容保存在名为order-keys.jq的文件中,并使用任务描述中的JSON作为输入,运行以下命令:
$ jq -M -n -c -f order-keys.jq
产生:
{"prop1":1,"prop3":true,"prop2":{"nested":0}}
好的,回答我的后续问题。这是我自己的hacky解决方案,将“剩余”的属性(未在顺序中指定)包含在结果对象的末尾,以便不会丢失任何输入:
def orderKeys(orderedkeys):
. as $in
| reduce keys[] as $key ({}; if orderedkeys|contains([$key]) then . else . + { ($key): $in[$key] } end)
| . as $rest
| reduce orderedkeys[] as $key ({}; . + { ($key): $in[$key] })
| . + $rest;
# Example:
orderKeys( ["prop1", "prop3", "prop2"] )
在输入上
{
"prop1": 1,
"otherprop": "foo",
"prop2": {
"nested": 0
},
"prop3": true
}
这将产生
{
"prop1": 1,
"prop3": true,
"prop2": {
"nested": 0
},
"otherprop": "foo"
}
to_entries
和from_entries
执行“对象减法”:{prop1, prop3, prop2} as $first
| $first + (to_entries - ($first|to_entries) | from_entries)
你唯一安全的选择是手动生成 JSON 字符串,并按照你想要的顺序排列属性。不能保证对象上设置属性的顺序会被保留。
你可以使用以下函数来实现:
def inorder(names): names as $names | . as $obj
| "{\($names | map("\(@json):\($obj[.])") | join(","))}"
;
接着使用它:
inorder(["prop1", "prop3", "prop2"])
python -mjson.tool file_name
。非常简单。 - Jason Hu