jshn.sh 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. # functions for parsing and generating json
  2. _json_get_var() {
  3. # dest=$1
  4. # var=$2
  5. eval "$1=\"\$${JSON_PREFIX}$2\""
  6. }
  7. _json_set_var() {
  8. # var=$1
  9. local ___val="$2"
  10. eval "${JSON_PREFIX}$1=\"\$___val\""
  11. }
  12. __jshn_raw_append() {
  13. # var=$1
  14. local value="$2"
  15. local sep="${3:- }"
  16. eval "export -- \"$1=\${$1:+\${$1}\${value:+\$sep}}\$value\""
  17. }
  18. _jshn_append() {
  19. # var=$1
  20. local _a_value="$2"
  21. eval "${JSON_PREFIX}$1=\"\${${JSON_PREFIX}$1} \$_a_value\""
  22. }
  23. _get_var() {
  24. # var=$1
  25. # value=$2
  26. eval "$1=\"\$$2\""
  27. }
  28. _set_var() {
  29. # var=$1
  30. local __val="$2"
  31. eval "$1=\"\$__val\""
  32. }
  33. _json_inc() {
  34. # var=$1
  35. # dest=$2
  36. let "${JSON_PREFIX}$1 += 1" "$2 = ${JSON_PREFIX}$1"
  37. }
  38. _json_add_generic() {
  39. # type=$1
  40. # name=$2
  41. # value=$3
  42. # cur=$4
  43. local var
  44. if [ "${4%%[0-9]*}" = "J_A" ]; then
  45. _json_inc "S_$4" var
  46. else
  47. var="${2//[^a-zA-Z0-9_]/_}"
  48. [[ "$var" == "$2" ]] || export -- "${JSON_PREFIX}N_${4}_${var}=$2"
  49. fi
  50. export -- \
  51. "${JSON_PREFIX}${4}_$var=$3" \
  52. "${JSON_PREFIX}T_${4}_$var=$1"
  53. _jshn_append "JSON_UNSET" "${4}_$var"
  54. _jshn_append "K_$4" "$var"
  55. }
  56. _json_add_table() {
  57. # name=$1
  58. # type=$2
  59. # itype=$3
  60. local cur seq
  61. _json_get_var cur JSON_CUR
  62. _json_inc JSON_SEQ seq
  63. local table="J_$3$seq"
  64. _json_set_var "U_$table" "$cur"
  65. export -- "${JSON_PREFIX}K_$table="
  66. unset "${JSON_PREFIX}S_$table"
  67. _json_set_var JSON_CUR "$table"
  68. _jshn_append "JSON_UNSET" "$table"
  69. _json_add_generic "$2" "$1" "$table" "$cur"
  70. }
  71. _json_close_table() {
  72. local _s_cur
  73. _json_get_var _s_cur JSON_CUR
  74. _json_get_var "${JSON_PREFIX}JSON_CUR" "U_$_s_cur"
  75. }
  76. json_set_namespace() {
  77. local _new="$1"
  78. local _old="$2"
  79. [ -n "$_old" ] && _set_var "$_old" "$JSON_PREFIX"
  80. JSON_PREFIX="$_new"
  81. }
  82. json_cleanup() {
  83. local unset tmp
  84. _json_get_var unset JSON_UNSET
  85. for tmp in $unset J_V; do
  86. unset \
  87. ${JSON_PREFIX}U_$tmp \
  88. ${JSON_PREFIX}K_$tmp \
  89. ${JSON_PREFIX}S_$tmp \
  90. ${JSON_PREFIX}T_$tmp \
  91. ${JSON_PREFIX}N_$tmp \
  92. ${JSON_PREFIX}$tmp
  93. done
  94. unset \
  95. ${JSON_PREFIX}JSON_SEQ \
  96. ${JSON_PREFIX}JSON_CUR \
  97. ${JSON_PREFIX}JSON_UNSET
  98. }
  99. json_init() {
  100. json_cleanup
  101. export -n ${JSON_PREFIX}JSON_SEQ=0
  102. export -- \
  103. ${JSON_PREFIX}JSON_CUR="J_V" \
  104. ${JSON_PREFIX}K_J_V=
  105. }
  106. json_add_object() {
  107. _json_add_table "$1" object T
  108. }
  109. json_close_object() {
  110. _json_close_table
  111. }
  112. json_add_array() {
  113. _json_add_table "$1" array A
  114. }
  115. json_close_array() {
  116. _json_close_table
  117. }
  118. json_add_string() {
  119. local cur
  120. _json_get_var cur JSON_CUR
  121. _json_add_generic string "$1" "$2" "$cur"
  122. }
  123. json_add_int() {
  124. local cur
  125. _json_get_var cur JSON_CUR
  126. _json_add_generic int "$1" "$2" "$cur"
  127. }
  128. json_add_boolean() {
  129. local cur
  130. _json_get_var cur JSON_CUR
  131. _json_add_generic boolean "$1" "$2" "$cur"
  132. }
  133. json_add_double() {
  134. local cur
  135. _json_get_var cur JSON_CUR
  136. _json_add_generic double "$1" "$2" "$cur"
  137. }
  138. json_add_null() {
  139. local cur
  140. _json_get_var cur JSON_CUR
  141. _json_add_generic null "$1" "" "$cur"
  142. }
  143. json_add_fields() {
  144. while [ "$#" -gt 0 ]; do
  145. local field="$1"
  146. shift
  147. local name="${field%%=*}"
  148. local val="${field#*=}"
  149. [ "$name" != "$val" ] || val=""
  150. local type="${name#*:}"
  151. [ "$type" != "$name" ] || type=string
  152. name="${name%%:*}"
  153. case "$type" in
  154. string|int|boolean|double)
  155. local cur
  156. _json_get_var cur JSON_CUR
  157. _json_add_generic "$type" "$name" "$val" "$cur"
  158. ;;
  159. esac
  160. done
  161. }
  162. # functions read access to json variables
  163. json_compact() {
  164. JSON_NONEWLINE=1
  165. JSON_INDENT=
  166. }
  167. json_pretty() {
  168. JSON_NONEWLINE=
  169. JSON_INDENT=1
  170. }
  171. json_load() {
  172. eval "`jshn -r "$1"`"
  173. }
  174. json_load_file() {
  175. eval "`jshn -R "$1"`"
  176. }
  177. json_dump() {
  178. jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} ${JSON_NONEWLINE:+-n} ${JSON_INDENT:+-i} -w
  179. }
  180. json_get_type() {
  181. local __dest="$1"
  182. local __cur
  183. _json_get_var __cur JSON_CUR
  184. local __var="${JSON_PREFIX}T_${__cur}_${2//[^a-zA-Z0-9_]/_}"
  185. eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]"
  186. }
  187. json_get_keys() {
  188. local __dest="$1"
  189. local _tbl_cur
  190. if [ -n "$2" ]; then
  191. json_get_var _tbl_cur "$2"
  192. else
  193. _json_get_var _tbl_cur JSON_CUR
  194. fi
  195. local __var="${JSON_PREFIX}K_${_tbl_cur}"
  196. eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]"
  197. }
  198. json_get_values() {
  199. local _v_dest="$1"
  200. local _v_keys _v_val _select=
  201. local _json_no_warning=1
  202. unset "$_v_dest"
  203. [ -n "$2" ] && {
  204. json_select "$2" || return 1
  205. _select=1
  206. }
  207. json_get_keys _v_keys
  208. set -- $_v_keys
  209. while [ "$#" -gt 0 ]; do
  210. json_get_var _v_val "$1"
  211. __jshn_raw_append "$_v_dest" "$_v_val"
  212. shift
  213. done
  214. [ -n "$_select" ] && json_select ..
  215. return 0
  216. }
  217. json_get_var() {
  218. local __dest="$1"
  219. local __cur
  220. _json_get_var __cur JSON_CUR
  221. local __var="${JSON_PREFIX}${__cur}_${2//[^a-zA-Z0-9_]/_}"
  222. eval "export -- \"$__dest=\${$__var:-$3}\"; [ -n \"\${$__var+x}\${3+x}\" ]"
  223. }
  224. json_get_vars() {
  225. while [ "$#" -gt 0 ]; do
  226. local _var="$1"; shift
  227. if [ "$_var" != "${_var#*:}" ]; then
  228. json_get_var "${_var%%:*}" "${_var%%:*}" "${_var#*:}"
  229. else
  230. json_get_var "$_var" "$_var"
  231. fi
  232. done
  233. }
  234. json_select() {
  235. local target="$1"
  236. local type
  237. local cur
  238. [ -z "$1" ] && {
  239. _json_set_var JSON_CUR "J_V"
  240. return 0
  241. }
  242. [[ "$1" == ".." ]] && {
  243. _json_get_var cur JSON_CUR
  244. _json_get_var cur "U_$cur"
  245. _json_set_var JSON_CUR "$cur"
  246. return 0
  247. }
  248. json_get_type type "$target"
  249. case "$type" in
  250. object|array)
  251. json_get_var cur "$target"
  252. _json_set_var JSON_CUR "$cur"
  253. ;;
  254. *)
  255. [ -n "$_json_no_warning" ] || \
  256. echo "WARNING: Variable '$target' does not exist or is not an array/object"
  257. return 1
  258. ;;
  259. esac
  260. }
  261. json_is_a() {
  262. local type
  263. json_get_type type "$1"
  264. [ "$type" = "$2" ]
  265. }
  266. json_for_each_item() {
  267. [ "$#" -ge 2 ] || return 0
  268. local function="$1"; shift
  269. local target="$1"; shift
  270. local type val
  271. json_get_type type "$target"
  272. case "$type" in
  273. object|array)
  274. local keys key
  275. json_select "$target"
  276. json_get_keys keys
  277. for key in $keys; do
  278. json_get_var val "$key"
  279. eval "$function \"\$val\" \"\$key\" \"\$@\""
  280. done
  281. json_select ..
  282. ;;
  283. *)
  284. json_get_var val "$target"
  285. eval "$function \"\$val\" \"\" \"\$@\""
  286. ;;
  287. esac
  288. }