-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscale-json
53 lines (47 loc) · 1.58 KB
/
scale-json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env bash
json() {
if declare -F "json.$1" >/dev/null 2>&1; then "json.$@"
elif [[ ${1-} == [-0-9]* ]]; then json.num "$1"
else
read -rd '' -a REPLY < <(compgen -A function json.)
json-fail 64 "invalid argument '$1'; must be one of: ${REPLY[*]/json./}"
fi
}
# Redefine this to change error handling
json-fail() { echo "$2" >&2; exit "$1"; }
json.map(){
(($#))||set -- ::block json-mapitem; local items=(); "$@"; REPLY=${items[@]+${items[*]}}; REPLY="{${REPLY%,}}"
}
json-mapitem() { json.str "$1"; local key=$REPLY; json "${@:2}"; items+=("$key:$REPLY,"); }
json.list(){
(($#))||set -- ::block json-listitem; local items=(); "$@"; REPLY=${items[@]+${items[*]}}; REPLY="[${REPLY%,}]"
}
json-listitem(){ json "$@"; items+=("$REPLY,"); }
json.json() { REPLY=$1; }
json.true() { REPLY=true; }
json.false(){ REPLY=false; }
json.null() { REPLY=null; }
json.int(){
[[ ${1-} =~ ^-?(0|[1-9][0-9]*)$ ]] || json-fail 65 "invalid json int: '$1'" || return
REPLY=$1
}
json.num(){
[[ ${1-} =~ ^-?(0|[1-9][0-9]*)([.][0-9]+)?([Ee][-+]?[0-9]+)?$ ]] ||
json-fail 65 "invalid json number: '$1'" || return
REPLY=$1
}
json.str(){
[[ $1 != *\\* ]] || set -- "${1//\\/\\\\}"
[[ $1 != *'"'* ]] || set -- "${1//\"/\\\"}"
if [[ $1 == *[[:cntrl:]]* ]]; then
set -- "${1//$'\n'/\\n}"; set -- "${1//$'\r'/\\r}"; set -- "${1//$'\t'/\\t}" # \n\r\t
if [[ $1 == *[[:cntrl:]]* ]]; then
local r s=${1//[^[:cntrl:]]}
while [[ $s ]]; do
printf -v r \\\\u%04x "'${s:0:1}"; set -- "${1//${s:0:1}/$r}"
s=${s//${s:0:1}/}
done
fi
fi
set -- "${1/#/\"}"; REPLY=${1/%/\"} # add surrounding quotes
}