/usr/lib/libubox/jshn.sh
JSONのパースや生成をシェルから行えるようにする。複数のライブラリを含む libubox の一部。
利用時には /usr/share/libubox/jshn.sh
をロードする。
JSONの例として WN-DX1167Rでのdump を用いる。
ロードされているJSONや関連変数のクリアを行い、新規に開始できる状態にする。
json_init
json_init
現在のシェル内へJSONをロードする。 _file
suffixが付く方は、文字通りファイルを指定してロードする。
json_load "str"
json_load_file /path/to/file
json_load "$(ubus call network.interface dump)"
json_load_file /tmp/json.txt
現在位置を指定したアレイまたはオブジェクトへ変更する。対象がアレイの場合、1始まりで数字を指定する。
json_select "target"
json_select ..
(一つ上位へ移動)
json_select "interface"
json_select 1
ロードされているJSONをダンプ表示する
json_dump [-i] [-n] [-o file]
-i
: インデントを付けるなどして整形済みフォーマットで出力する
-n
: 末尾に改行を付加しない
-o file
: 指定した file に出力する
json_dump
(WRC-300GHBK2-I)
root@OpenWrt:~# json_dump
{ "interface": [ { "interface": "lan", "up": true, "pending": false, "available": true, "autostart": true, "dynamic": false, "uptime": 128, "l3_device": "br-lan", "proto": "static", "device": "br-lan", "updated": [ "addresses" ], "metric": 0, "dns_metric": 0, "delegation": true, "ipv4_address": [ { "address": "192.168.10.1", "mask": 24 } ], "ipv6_address": [ ], "ipv6_prefix": [ ], "ipv6_prefix_assignment": [ { "address": "fd2b:311c:da99:4::", "mask": 62, "local_address": { "address": "fd2b:311c:da99:4::1", "mask": 62 } }, { "address": "fdff:7b72:e42d::", "mask": 60, "local_address": { "address": "fdff:7b72:e42d::1", "mask": 60 } } ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ], "inactive": { "ipv4_address": [ ], "ipv6_address": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ] }, "data": { } }, { "interface": "loopback", "up": true, "pending": false, "available": true, "autostart": true, "dynamic": false, "uptime": 128, "l3_device": "lo", "proto": "static", "device": "lo", "updated": [ "addresses" ], "metric": 0, "dns_metric": 0, "delegation": true, "ipv4_address": [ { "address": "127.0.0.1", "mask": 8 } ], "ipv6_address": [ ], "ipv6_prefix": [ ], "ipv6_prefix_assignment": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ], "inactive": { "ipv4_address": [ ], "ipv6_address": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ] }, "data": { } }, { "interface": "wan", "up": true, "pending": false, "available": true, "autostart": true, "dynamic": false, "uptime": 96, "l3_device": "eth0.2", "proto": "dhcp", "device": "eth0.2", "updated": [ "addresses", "routes", "data" ], "metric": 0, "dns_metric": 0, "delegation": true, "ipv4_address": [ { "address": "192.168.90.210", "mask": 24 } ], "ipv6_address": [ ], "ipv6_prefix": [ ], "ipv6_prefix_assignment": [ ], "route": [ { "target": "0.0.0.0", "mask": 0, "nexthop": "192.168.90.1", "source": "192.168.90.210\/32" } ], "dns_server": [ "192.168.90.1" ], "dns_search": [ "lan" ], "neighbors": [ ], "inactive": { "ipv4_address": [ ], "ipv6_address": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ] }, "data": { "hostname": "OpenWrt", "leasetime": 43200 } }, { "interface": "wan6", "up": true, "pending": false, "available": true, "autostart": true, "dynamic": false, "uptime": 81, "l3_device": "eth0.2", "proto": "dhcpv6", "device": "eth0.2", "updated": [ "addresses", "routes", "prefixes", "data" ], "metric": 0, "dns_metric": 0, "delegation": true, "ipv4_address": [ ], "ipv6_address": [ { "address": "fd2b:311c:da99::ade", "mask": 128 } ], "ipv6_prefix": [ { "address": "fd2b:311c:da99:4::", "mask": 62, "class": "wan6", "assigned": { "lan": { "address": "fd2b:311c:da99:4::", "mask": 62 } } } ], "ipv6_prefix_assignment": [ ], "route": [ { "target": "::", "mask": 0, "nexthop": "fe80::a612:42ff:fe78:82a0", "metric": 4096, "source": "fd2b:311c:da99:4::\/62" }, { "target": "::", "mask": 0, "nexthop": "fe80::a612:42ff:fe78:82a0", "metric": 4096, "source": "fd2b:311c:da99::ade\/128" } ], "dns_server": [ "fd2b:311c:da99::1" ], "dns_search": [ ], "neighbors": [ ], "inactive": { "ipv4_address": [ ], "ipv6_address": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ] }, "data": { "passthru": "00170010fd2b311cda9900000000000000000001" } } ] }
指定した要素のtypeを取得して変数に格納する。
json_get_type dest target
json_get_type TYPE interface
root@OpenWrt:/tmp/jshn# json_load "$(ubus call network.interface dump)"
root@OpenWrt:/tmp/jshn# json_get_type TYPE "interface"
root@OpenWrt:/tmp/jshn# echo $TYPE
array
指定したキーの値を変数に格納する。
json_get_var dest key
json_get_var VALUE interface
root@OpenWrt:/tmp/jshn# json_load "$(ubus call network.interface dump)"
root@OpenWrt:/tmp/jshn# json_select interface
root@OpenWrt:/tmp/jshn# json_select 1
root@OpenWrt:/tmp/jshn# json_get_var VALUE interface
root@OpenWrt:/tmp/jshn# echo $VALUE
lan
root@OpenWrt:/tmp/jshn# json_get_var VALUE l3_device
root@OpenWrt:/tmp/jshn# echo $VALUE
br-lan
現在位置または第2引数で指定された、アレイまたはオブジェクト内のキーを全て取得し変数に格納する。
json_get_keys dest [target]
json_get_keys KEYS
json_get_keys KEYS interface
root@OpenWrt:/tmp/jshn# json_load "$(ubus call network.interface dump)"
root@OpenWrt:/tmp/jshn# json_get_keys KEYS
root@OpenWrt:/tmp/jshn# echo $KEYS
interface
root@OpenWrt:/tmp/jshn# json_get_keys KEYS interface
root@OpenWrt:/tmp/jshn# echo $KEYS
1 2 3 4
現在位置または第2引数で指定された、オブジェクト内のキーを全て取得し変数に格納する。
値がアレイまたはオブジェクトである場合、 J_Axx
または J_Txx
という形式の文字列が出てくる。
json_get_values dest [target]
json_get_values VALUES
json_get_values VALUES 1
root@OpenWrt:/tmp/jshn# json_load "$(ubus call network.interface dump)"
root@OpenWrt:/tmp/jshn# json_select interface
root@OpenWrt:/tmp/jshn# json_get_values VALUES
root@OpenWrt:/tmp/jshn# echo $VALUES
J_T2 J_T25 J_T44 J_T63
root@OpenWrt:/tmp/jshn# json_get_values VALUES 1
root@OpenWrt:/tmp/jshn# echo $VALUES
lan 1 0 1 1 0 362723 br-lan static br-lan J_A3 0 0 1 J_A4 J_A6 J_A7 J_A8 J_A13 J_A14 J_A15 J_A16 J_T17 J_T24
指定したキーの値をキーと同名の変数に格納する。function内である場合は、キー名を予めlocalで宣言しておくでスコープを限定することも可。
json_get_vars key1 key2 key3 key4 ...
json_get_vars interface up l3_device metric
root@OpenWrt:/tmp/jshn# json_load "$(ubus call network.interface dump)"
root@OpenWrt:/tmp/jshn# json_select interface
root@OpenWrt:/tmp/jshn# json_select 1
root@OpenWrt:/tmp/jshn# json_get_vars interface up l3_device metric
root@OpenWrt:/tmp/jshn# echo $interface
lan
root@OpenWrt:/tmp/jshn# echo $up
1
root@OpenWrt:/tmp/jshn# echo $l3_device
br-lan
root@OpenWrt:/tmp/jshn# echo $metric
0
キー/値のペアを追加する関数では、アレイに値のみ追加するにはキー名を空 ""
にする。
現在の位置へキーと文字列値のペアを追加する。
json_add_string key value
json_add_string "domain" "wiki.taiha.net"
root@OpenWrt:~# json_add_string "domain" "wiki.taiha.net"
root@OpenWrt:~# json_dump
{ "domain": "wiki.taiha.net" }
現在の位置へキーとint値のペアを追加する
json_add_int key value
`json_add_int "count" "2"
root@OpenWrt:~# json_add_int "count" "2"
root@OpenWrt:~# json_dump
{ "count": 2 }
現在の位置にキーとbool値のペアを追加する。
json_add_boolean key value
json_add_boolean "enabled" "1"
root@OpenWrt:~# json_add_boolean "enabled" "1"
root@OpenWrt:~# json_dump
{ "enabled": true }
root@OpenWrt:~# json_add_boolean "enabled" "0"
root@OpenWrt:~# json_dump
{ "enabled": false }
現在の位置にキーとdouble値のペアを追加する。
json_add_double key value
`json_add_double "pie" "3.14"
root@OpenWrt:~# json_add_double "pie" "3.14"
root@OpenWrt:~# json_dump
{ "pie": 3.1400000000000001 }
内部的な扱いの関係か、ズレが出た。
現在の位置にキーとnull値のペアを追加する。
json_add_null key
`json_add_null "nu"
root@OpenWrt:~# json_add_null "nu"
root@OpenWrt:~# json_dump
{ "nu": null }
現在の位置にオブジェクトを追加する。追加後、現在位置は自動的にそのオブジェクト内へ移る。
オブジェクトを抜ける際は json_close_object
で上位に移る。
(json_select ..
でも移れたりする。ぶっちゃけ違いがまだよくわからない)
アレイに無名オブジェクトを追加する場合、パラメータを付けず呼び出す。
json_add_object "target"
json_add_object "newobj"
root@OpenWrt:~# json_dump
{ }
root@OpenWrt:~# json_add_object newobj
root@OpenWrt:~# json_dump
{ "newobj": { } }
現在の位置にアレイを追加する。追加後、現在位置は自動的にそのアレイ内へ移る。
アレイを抜ける際は json_close_array
で上位に移る。
(これもオブジェクトと同様 json_select ..
でも移れるがよくわからない)
json_add_array "target"
json_add_array "ifaces"
root@OpenWrt:~# json_add_array "ifaces"
root@OpenWrt:~# json_dump
{ "ifaces": [ ] }
現在使用中の名前空間を切り替え、第2引数がある場合はそれを変数名として旧名前空間名を格納する。
現在の名前空間名は環境変数 JSON_PREFIX
に格納される。
json_init
を行う場合、対象の名前空間に切り替えたうえで行う必要がある。
json_set_namespace new var
json_set_namespace "iface" "old"
json_set_namespace "$old"
root@OpenWrt:~# json_load "$(ubus call system board)"
root@OpenWrt:~# json_dump
{ "kernel": "4.19.79", "hostname": "OpenWrt", "system": "Qualcomm Atheros QCA956X ver 1 rev 0", "model": "ELECOM WRC-300GHBK2-I", "board_name": "elecom,wrc-300ghbk2-i", "release": { "distribution": "OpenWrt", "version": "SNAPSHOT", "revision": "r0+11364-af93d5003c", "target": "ath79\/generic", "description": "OpenWrt SNAPSHOT r0+11364-af93d5003c" } }
root@OpenWrt:~# json_set_namespace "iface" "old"
root@OpenWrt:~# echo $old
root@OpenWrt:~# echo $JSON_PREFIX
iface
root@OpenWrt:~# json_load "$(ifstatus wan)"
root@OpenWrt:~# json_dump
{ "up": true, "pending": false, "available": true, "autostart": true, "dynamic": false, "uptime": 4569, "l3_device": "eth0.2", "proto": "dhcp", "device": "eth0.2", "updated": [ "addresses", "routes", "data" ], "metric": 0, "dns_metric": 0, "delegation": true, "ipv4_address": [ { "address": "192.168.90.210", "mask": 24 } ], "ipv6_address": [ ], "ipv6_prefix": [ ], "ipv6_prefix_assignment": [ ], "route": [ { "target": "0.0.0.0", "mask": 0, "nexthop": "192.168.90.1", "source": "192.168.90.210\/32" } ], "dns_server": [ "192.168.90.1" ], "dns_search": [ "lan" ], "neighbors": [ ], "inactive": { "ipv4_address": [ ], "ipv6_address": [ ], "route": [ ], "dns_server": [ ], "dns_search": [ ], "neighbors": [ ] }, "data": { "hostname": "OpenWrt", "leasetime": 43200 } }
root@OpenWrt:~# json_set_namespace "$old" "old"
root@OpenWrt:~# echo $old
iface
root@OpenWrt:~# echo $JSON_PREFIX
root@OpenWrt:~# json_dump
{ "kernel": "4.19.79", "hostname": "OpenWrt", "system": "Qualcomm Atheros QCA956X ver 1 rev 0", "model": "ELECOM WRC-300GHBK2-I", "board_name": "elecom,wrc-300ghbk2-i", "release": { "distribution": "OpenWrt", "version": "SNAPSHOT", "revision": "r0+11364-af93d5003c", "target": "ath79\/generic", "description": "OpenWrt SNAPSHOT r0+11364-af93d5003c" } }