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