jq 命令可以方便快捷的解析 json 格式的数据。下面几个例子简单的记录了 jq 命令的用法。其中 task_feature_file 中的每一行都是一个 json 格式的数据。

解析 json 格式的数据

1
cat task_feature_file | jq .

根据 key[cms_data] 获取 value

1
cat task_feature_file | jq '.cms_data'

根据 key 获取 value(嵌套提取)

1
cat task_feature_file | jq '.cms_data.res_id'

提取所有 key

1
cat task_feature_file | jq 'keys'

提取所有 key(嵌套提取)

1
cat task_feature_file | jq '.cms_data' | jq 'keys'

判断是否有某个 key

1
cat task_feature_file | jq 'has("cms_data")'

转换数字为字符串 How do I use jq to convert number to string?

Given the following jq command and Json:

1
2
3
4
5
6
7
8
9
10
11
12
jq '.[]|[.string,.number]|join(": ")' <<< '
[
{
"number": 3,
"string": "threee"
},
{
"number": 7,
"string": "seven"
}
]
'

I’m trying to format the output as:

1
2
three: 3
seven: 7

方法:The jq command has the tostring function. It took me a while to learn to use it by trial and error. Here is how to use it:

1
2
3
4
5
6
jq -r '.[] | [ .string, .number|tostring ] | join(": ")' <<< '
[{ "number": 9, "string": "nine"},
{ "number": 4, "string": "four"}]
'
#nine: 9
#four: 4

转换 json 对象为 key=value 形式,How to convert a JSON object to key=value format in jq?

In jq, how can I convert a JSON to a string with key=value?

From:

1
2
3
4
5
6
jq -r '.[] | [ .string, .number|tostring ] | join(": ")' <<< '
[{ "number": 9, "string": "nine"},
{ "number": 4, "string": "four"}]
'
#nine: 9
#four: 4

To:

1
2
3
var=1
foo=bar
x=test

方法:You could try:

1
jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" test.json

Here’s a demo:

1
2
3
4
5
6
7
8
9
10
11
$ cat test.json
{
"var": 1,
"foo": "bar",
"x": "test"
}
$ jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" test.json

#foo=bar
#var=1
#x=test

或者可以使用:

1
2
3
4
5
6
7
8
$ cat data.json
{
"SITE_DATA": {
"URL": "example.com",
"AUTHOR": "John Doe",
"CREATED": "10/22/2017"
}
}

You can make a much simpler version of the jq program:

1
jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""'

which outputs:

1
2
3
URL="example.com"
AUTHOR="John Doe"
CREATED="10/22/2017"

This string is evalable as long as the characters `, $, newline and null don’t appear in the data:

1
2
eval "$(jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""' < data.json)"
echo "$AUTHOR"

或者:

Just realized that I can loop over the results and eval each iteration:

1
2
3
4
constants=$(cat ${1} | jq '.SITE_DATA' | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]")
for key in ${constants}; do
eval ${key}
done

Allows me to do:

1
2
echo ${AUTHOR}
# outputs John Doe

将输出化为一行 Get outputs from jq on a single line

-c is what you likely need

Using the output you posted above, you can process it further:

1
jq -c . input

To Give;

1
2
{"key":"SEA-739","status":"Open","assignee":null}
{"key":"SEA-738","status":"Resolved","assignee":"user2@mycompany.com"}

Or you can just change your original command

FROM

1
jq -r '(.issues[] | {key, status: .fields.status.name, assignee: .fields.assignee.emailAddress})'

TO

1
jq -c '(.issues[] | {key, status: .fields.status.name, assignee: .fields.assignee.emailAddress})'

json 数组转 bash 数组 parse one field from an JSON array into bash array

I have a JSON output that contains a list of objects stored in a variable. (I may not be phrasing that right)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[
{
"item1": "value1",
"item2": "value2",
"sub items": [
{
"subitem": "subvalue"
}
]
},
{
"item1": "value1_2",
"item2": "value2_2",
"sub items_2": [
{
"subitem_2": "subvalue_2"
}
]
}
]

Using jq :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat json
[
{
"item1": "value1",
"item2": "value2",
"sub items": [
{
"subitem": "subvalue"
}
]
},
{
"item1": "value1_2",
"item2": "value2_2",
"sub items_2": [
{
"subitem_2": "subvalue_2"
}
]
}
]

CODE:

1
2
arr=( $(jq -r '.[].item2' json) )
printf '%s\n' "${arr[@]}"

OUTPUT:

1
2
value2
value2_2

jq 遍历 json 数组,遍历 json 对象,Bash for Loop Over JSON Array Using jq

First we will start with some data:

1
2
sample='[{"name":"foo"},{"name":"bar"}]'  
echo "${sample}" | jq '.'

输出

1
2
3
4
5
6
7
8
[
{
"name": "foo"
},
{
"name": "bar"
}
]

By using jq --compact-output (or -c) we can get each object on a newline.

1
2
sample='[{"name":"foo"},{"name":"bar"}]'  
echo "${sample}" | jq -c '.[]'

输出

1
2
{"name":"foo"}
{"name":"bar"}

We could start iterating of the above with a Bash for loop if our data does not contain spaces or newlines. But since certificates contain newlines we better base64 encode each line. Also, instead of -c, we now use -r to get rid of the extra quotes.

1
2
sample='[{"name":"foo"},{"name":"bar"}]'  
echo "${sample}" | jq -r '.[] | @base64'

输出

1
2
eyJuYW1lIjoiZm9vIn0=  
eyJuYW1lIjoiYmFyIn0=

Now let’s build our for loop.

1
2
3
4
5
6
7
sample='[{"name":"foo"},{"name":"bar"}]'  
for row in $(echo "${sample}" | jq -r '.[] | @base64'); do
_jq() {
echo ${row} | base64 --decode | jq -r ${1}
}
echo $(_jq '.name')
done

输出

1
2
foo
bar

实例:

1
2
3
4
5
6
7
cat test.json | jq -c -r ".[] | {status : .status}" | while read row
do
_jq() {
echo ${row} | jq -r ${1}
}
echo $(_jq '.status')
done

以上代码等同于:

1
2
3
4
5
6
7
cat test.json | jq -r ".[] | {status: .status} | @base64"  | while read row
do
_jq() {
echo ${row} | base64 --decode | jq -r ${1}
}
echo $(_jq '.status')
done

解决报错:parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 3, column 9 或者 jq: error (at :1): Cannot index string with string “expand”

Newlines not supported on jqplay with jq 1.5. They must be escaped as \n or as \u000a.

一般原因是因为 jq 1.5的版本不知道 json 换行,解决方法如下:

1
2
3
4
json_string=$(echo ${string} | tr '\r\n' ' ')

#或者采用直接删除的方式
json_string=$(echo ${string} | tr -d '\r\n')

通过 tr 函数做一个替换即可!