以下介紹OpenWrt 中的jshn.sh。
1. jshn
是一個生成或分析JSON 格式的小工具,其程試碼在libubox 的jshn.c。jshn.sh 則提供各個操作JSON 的API,可以在自己實作的script 中,透過其API 生成或分析JSON 資料。jshn.sh
可以在OpenWrt 系統中,/usr/share/libubox 下找到。
2. 介紹jshn.sh 前,先簡單介紹JSON。
JSON 的資料格試為:
key:value
其中key必須在雙引號””中,value可以是
- 數字 (int 或double )
- 字串 (string)
- 布林值 (boolean)
- 物件 (object)
- 陣列 (array)
- null
數字:
{"number1":100,"number2":1.23}
字串:
{"name":"Tom"}
布林值:
{"up":false,"down":true}
物件:必須在大括號{}
中。
{"Influencer":{"name":"Tom","age":"42","city","New York"}}
陣列:必須在中括號[]中,陣列值必須是字串、數字、物件、陣列、布林值或 null 類型。
{"dns-server":[ "1.1.1.1", "8.8.8.8" ]}
在上面的例子中,為一個有二個字串的陣列。
{"ipv4-address":[ {"address":"192.168.1.102","mask":24}, {"address": "192.168.2.103","mask":24} ]}
在上面的例子中,為一個有二個物件的陣列。
3. jshn.sh
提供以下API:
- json_add_string
- json_add_int
- json_add_double
- json_add_boolean
- json_add_null
- json_add_object、json_close_object
- json_add_array、json_close_array
- json_load、json_load_file
- json_dump
- json_select
- json_get_type
- json_get_keys
- json_get_values
- json_get_var
- json_is_a
- json_for_each_item
json_add_string、json_add_int、json_add_double、json_add_boolean、json_add_null :
#!/bin/sh . /usr/share/libubox/jshn.sh json_init json_add_string "msg" "hello,world" json_add_int "uptime" 100 json_add_double "angle" 36.1 json_add_boolean "up" false json_add_null "device"
生成JSON為 {"msg":"hello.world","uptime":100,"angle":36.1,"up":false,"device":null}
json_add_object、json_close_object :
#!/bin/sh . /usr/share/libubox/jshn.sh json_init json_add_object "test" json_close_object json_add_object "appliaction" json_add_string "version" "0.0.1" json_add_object "script" json_add_string "start" "node ./bin/www" json_close_object json_close_object
生成JSON為 {"test":{}, "application":{"version":"0.0.1","script":{"start":"node ./bin/www"}}}
須注意add object 完成之後,必須close object。
json_add_array、json_close_array :
#!/bin/sh . /usr/share/libubox/jshn.sh json_init json_add_array "test" json_close_array json_add_array "dns-server" json_add_string "" "1.1.1.1" #在array中,增加第一個string值 json_add_string "" "8.8.8.8" #在array中,增加第二個string值 json_close_array json_add_array "ipv4-address" json_add_object "" #在array中,增加第一個object值 json_add_string "address" "192.168.1.100" json_add_int "mask" 24 json_close_object json_add_object "" #在array中,增加第二個object值 json_add_string "address" "192.168.2.100" json_add_int "mask" 24 json_close_object json_close_array
生成JSON為 {"test":[], "dsn-server":["1.1.1.1","8.8.8.8"], "ipv4-address":[ {"address":"192.168.1.100","mask":24}, {"address":"192.168.2.100","mask":24} ]}
須注意add array 完成之後,必須close array。
json_load、json_load_file、json_dump :
#!/bin/sh . /usr/share/libubox/jshn.sh json_data="{\"msg\":\"hello,world\"}" json_load $json_data dump_json_data=$(json_dump) echo $dump_json_data
執行結果為 {"msg":"hello,world"}
若有一檔案json_file,位於tmp,其內容如下:
{"msg":"hello,world"}
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" dump_json_data=$(json_dump) echo $dump_json_data
執行結果為 {"msg":"hello,world"}
json_load 可以讀取一JSON 格式字串,json_load_file 可以讀取一個內容為JSON 格式的文件。讀取之後,可以透過json_dump 將JSON 資料取出。
json_select :
是用來選擇JSON 中的object
或array
。以下面JSON 為範列:
{ #第一層 "msg": "hello, world", # "up": false, # "uptime": 100, # "interface": "eth0.2", # "angle": 36.1, # "device": null, # "application": { #第二層application "version": "0.0.1", # "script": { #第三層script "start": "node ./bini/www" # } #第三層script結尾 }, #第二層application結尾 "dns-server": [ #第二層dns-server "1.1.1.1", # "8.8.8.8" # ], #第二層dns-server結尾 "ipv4-address": [ #第二層ipv4-address { #第三層object1 "address": "192.168.1.102", # "mask": 24 # }, #第三層object1結尾 { #第三層object2 "address": "192.168.2.103", # "mask": 24 # } #第三層object2結尾 ] #第二層ipv4-address結尾 } #第一層結尾
以上面JSON 範例,若要選擇第二層application object,則執行 json_select "application" 要跳回第一層,則再執行 json_select .. 若要選擇第三層script object,則需執行 json_select "application" json_selct "script" 要跳回第一層,則需執行 json_select .. json_select ..
將JSON 中的object 或array,類推為目錄(文件夾);JSON 中的key 值,類推為檔案。因此,可以將JSON 資料類推如下:
所以json_select 就如指令cd
一樣。返回上一層就使用
json_select ..
若要到指定的object 或array (到指定的目錄),就使用
json_select "object 或array 名稱"
json_get_type :
是用來得到值的類型。以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" json_get_type type "msg" echo $type json_get_type type "up" echo $type json_get_type type "uptime" echo $type json_get_type type "interface" echo $type json_get_type type "angle" echo $type json_get_type type "device" echo $type json_get_type type "application" echo $type json_get_type type "dns-server" echo $type
執行結果為 string boolean int string double null object array
json_get_keys :
是用來得到目前object 下的所有key 值。以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" json_get_keys keys echo $keys json_select "application" #object json_get_keys keys echo $keys json_select .. json_select "dns-server" #array json_get_keys keys echo $keys
執行結果為 msg up uptime interface angle application dns-server version script 1 2
json_get_values :
是用來得到目前object 下的所有value 值。以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" json_get_values values echo $values
執行結果為 hello,world 0 100 eth0.2 36.100000
json_get_var :
是用來得到指定key 時,相對應的value 值。以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" json_get_var tmp "msg" echo $tmp json_select "application" #指定到第二層application json_get_var tmp "version" echo $tmp json_select "script" #指定到第三層script json_get_var tmp "start" echo $tmp json_select .. #回到第二層application json_select .. #回到第一層 json_select "dns-server" json_get_var tmp 1 #讀取array的第一個key,所對應的value值 echo $tmp json_get_var tmp 2 #讀取array的第二個key,所對應的value值 echo $tmp
執行結果為 hello,world 0.0.1 node ./bin/www 1.1.1.1 8.8.8.8
json_is_a :
用於判斷value 值的類型。以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" json_select "dns-server" idx=1 while json_is_a $idx string do json_get_var tmp $idx echo $tmp idx=$((idx+1)) done
執行結果為 1.1.1.1 8.8.8.8
json_for_each_item :
以下面JSON 為範列,/tmp/json_file 如下:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], "ipv4-address": [ { "address": "192.168.1.102", "mask": 24 }, { "address": "192.168.2.103", "mask": 24 } ] }
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_file" myprint1() { echo $1--$2 } myprint2(){ json_select $2 json_get_var tmp "address" echo $tmp json_select .. } json_for_each_item myprint1 "dns-server" json_for_ecth_item myprint2 "ipv4-address"
執行結果為 1.1.1.1--1 8.8.8.8--2 192.168.1.102 192.168.2.103
4. 範例:
{ "msg": "hello, world", "up": false, "uptime": 100, "interface": "eth0.2", "angle": 36.1, "device": null, "application": { "version": "0.0.1", "script": { "start": "node ./bini/www" } }, "dns-server": [ "1.1.1.1", "8.8.8.8" ], "ipv4-address": [ { "address": "192.168.1.102", "mask": 24 }, { "address": "192.168.2.103", "mask": 24 } ] }
根據上面JSON 資料,可以使用以下script 生成。
#!/bin/sh . /usr/share/libubox/jshn.sh json_init json_add_string "msg" "hello, world" json_add_boolean "up" false json_add_int "uptime" 100 json_add_string "interface" "eth0.2" json_add_double "angle" 36.1 json_add_null "device" json_add_object "application" json_add_string "version" "0.0.1" json_add_object "script" json_add_string "start" "node ./bini/www" json_close_object json_close_object json_add_array "dns-server" json_add_string "" "1.1.1.1" json_add_string "" "8.8.8.8" json_close_array json_add_array "ipv4-address" json_add_object "" json_add_string "address" "192.168.1.102" json_add_int "mask" 24 json_close_object json_add_object "" json_add_string "address" "192.168.2.103" json_add_int "mask" 24 json_close_object json_close_array json=$(json_dump) echo $json
執行結果如下:
檔案/tmp/json_data 如下:
使用以下script 驗證:
#!/bin/sh . /usr/share/libubox/jshn.sh json_load_file "/tmp/json_data" json_get_var tmp "msg" echo "msg="$tmp json_get_var tmp "up"e cho "up="$tmp json_get_var tmp "uptime" echo "uptime="$tmp json_get_var tmp "interface" echo "interface="$tmp json_get_var tmp "angle" echo "angle="$tmp json_get_var tmp "device" echo "device="$tmp json_select "application" json_get_var tmp "version" echo "version="$tmp json_select "script" json_get_var tmp "start" echo "start="$tmp json_select .. json_select .. json_select "dns-server" idx=1 while json_is_a $idx string do json_get_var tmp $idx echo $idx"="$tmp idx=$((idx+1)) done json_select .. json_select "ipv4-address" idx=1 while json_is_a $idx object do json_select $idx json_get_var tmp "address" echo "address="$tmp json_get_var tmp "mask" echo "mask="$tmp json_select .. idx=$((idx+1)) done
其執行結果如下: