]> git.plutz.net Git - cgilite/blob - json.sh
get json values via jpath
[cgilite] / json.sh
1 #!/bin/sh
2
3 # [ -n "$include_json" ] && return 0
4 # include_json="$0"
5
6 . "${_EXEC:-.}/cgilite/db23.sh"
7
8 debug(){ [ $# -gt 0 ] && printf '%s\n' "$@" >&2 || tee -a /dev/stderr; }
9
10 json_except() {
11   printf '%s\n' "$@" >&2;
12   printf 'Exc: %s\n' "$json_document" >&2
13 }
14
15 json_space() {
16   while true; do case "$json_document" in
17     [" ${BR}${CR}       "]*) json_document="${json_document#?}";;
18     *) break ;;
19   esac; done
20 }
21
22 json_string() {
23   local string json_document="$json_document" end=0
24
25   json_space
26   case $json_document in
27     \"*) json_document="${json_document#?}"
28       ;;
29     *) json_except "Expected string specifyer starting with (\")"
30       return 1
31       ;;
32   esac
33   while [ "$json_document" ]; do case $json_document in
34     \\?*)
35       string="${string}${json_document%"${json_document#??}"}"
36       json_document="${json_document#??}"
37       ;;
38     \"*)
39       json_document="${json_document#?}"
40       end=1
41       break
42       ;;
43     *) 
44       string="${string}${json_document%"${json_document#?}"}"
45       json_document="${json_document#?}"
46       ;;
47   esac; done
48
49   if [ $end -eq 0 ]; then
50     json_except "Document ended mid-string"
51     return 1
52   fi
53
54   printf "%s    %s\n" "$(STRING "$string")" "$json_document"
55 }
56
57 json_key() {
58   local key json_document="$json_document"
59
60   json_space
61   case $json_document in
62     \"*)
63       key="$(json_string)" || return 1
64       json_document="${key#*    }"
65       key="${key%%      *}"
66       ;;
67     *) json_except "Expected key specifyer starting with '\"'"
68       return 1
69       ;;
70   esac
71   json_space
72   case $json_document in
73     :*) json_document="${json_document#?}"
74       ;;
75     *) json_except "Expected value separator \":\""
76       return 1
77       ;;
78   esac
79
80   printf '%s    %s\n' "$key" "$json_document"
81 }
82
83 json_number() {
84   local number json_document="$json_document"
85
86   json_space
87   number="${json_document%%["   ${BR}${CR} ,}]"]*}"
88   json_document="${json_document#"$number"}"
89   if ! number="$(printf %f "$number")"; then
90     json_except "Invalid number format"
91     return 1
92   fi
93
94   printf '%s    %s\n' "num:${number%.000000}" "$json_document"
95 }
96
97 json_value() {
98   local value json_document="$json_document"
99   json_type=""
100
101   json_space
102   case $json_document in
103     \"*)
104       value="$(json_string)" || return 1
105       json_document="${value#*  }"
106       value="str:${value%%      *}"
107       json_type=string
108       ;;
109     [+-.0-9]*)
110       value="$(json_number)" || return 1
111       json_document="${value#*  }"
112       value="${value%%  *}"
113       json_type=number
114       ;;
115     "{"*)
116       value="$(json_object)" || return 1
117       json_document="${value#*  }"
118       value="obj:${value%%      *}"
119       json_type=object
120       ;;
121     "["*)
122       value="$(json_array)" || return 1
123       json_document="${value#*  }"
124       value="arr:${value%%      *}"
125       json_type=array
126       ;;
127     null*)
128       json_document="${json_document#null}"
129       value="null"
130       json_type=null
131       ;;
132     true*)
133       json_document="${json_document#true}"
134       value="true"
135       json_type=boolean
136       ;;
137     false*)
138       json_document="${json_document#false}"
139       value="false"
140       json_type=boolean
141       ;;
142   esac
143
144   printf "%s    %s\n" "$value" "$json_document"
145 }
146
147 json_array() {
148   local struct="$(DB2 new)" value json_document="$json_document"
149
150   json_space
151   case $json_document in
152     "["*) json_document="${json_document#?}"
153       ;;
154     *) json_except "Expected array starting with \"[\""
155       return 1
156       ;;
157   esac
158
159   json_space
160   case $json_document in
161     "]"*)
162       printf "%s        %s\n" "" "${json_document#?}"
163       return 0
164       ;;
165   esac
166
167   while :; do
168     json_space
169
170     value="$(json_value)" || return 1
171     json_document="${value#*    }"
172     value="$(UNSTRING "${value%%        *}")"
173
174        struct="$(DB2 "$struct" append "@" "$value")" \
175     || struct="$(DB2 "$struct" set    "@" "$value")"
176
177     json_space
178     case $json_document in
179       ,*) json_document="${json_document#?}"
180         ;;
181       "]"*) json_document="${json_document#?}"
182         break
183         ;;
184       *) json_except "Unexpected character mid-array"
185         return 1
186         ;;
187     esac
188   done
189
190   printf "%s    %s\n" "$(STRING "$struct")" "$json_document"
191 }
192
193 json_object() {
194   local struct="$(DB2 new)" key value json_document="$json_document"
195
196   json_space
197   case $json_document in
198     "{"*) json_document="${json_document#?}"
199       ;;
200     *) json_except "Expected object starting with \"{\""
201       return 1
202       ;;
203   esac
204
205   json_space
206   case $json_document in
207     "}"*)
208       printf "%s        %s\n" "" "${json_document#?}"
209       return 0
210       ;;
211   esac
212
213   while :; do
214     json_space
215
216     key="$(json_key)" || return 1
217     json_document="${key#*      }"
218     key="$(UNSTRING "${key%%    *}")"
219
220     value="$(json_value)" || return 1
221     json_document="${value#*    }"
222     value="$(UNSTRING "${value%%        *}")"
223
224     struct="$(DB2 "$struct" set "$key" "$value")"
225
226     json_space
227     case $json_document in
228       ,*) json_document="${json_document#?}"
229         ;;
230       "}"*) json_document="${json_document#?}"
231         break
232         ;;
233       *) json_except "Unexpected character mid-object"
234         return 1
235         ;;
236     esac
237   done
238
239   printf "%s    %s\n" "$(STRING "$struct")" "$json_document"
240 }
241
242 json_load() {
243   local json_document="$1"
244
245   json_value
246 }
247
248 json_get() {
249   local json="$1" jpath="${2#.}" id idx
250   json_type=''
251
252   case $json in
253     str:*) json_type="string";;
254     arr:*) json_type="array";;
255     obj:*) json_type="object";;
256     num:*) json_type="number";;
257     true|false)
258            json_type="boolean";;
259     null)  json_type="null";;
260   esac
261   json="${json#???:}"
262
263   case $jpath in
264     "")
265       printf %s\\n "$json"
266       return 0
267       ;;
268     "["[0-9]*"]"*)
269       idx="${jpath%%"]"*}" idx="${idx#"["}"
270       jpath="${jpath#"["*"]"}"
271       ;;
272     "['"*"']"*)
273       id="${jpath%%"']"*}" id="${id#"['"}"
274       jpath="${jpath#"['"*"']"}"
275       ;;
276     *) id="${jpath%%[".["]*}"
277       jpath="${jpath#"$id"}"
278       ;;
279   esac
280
281   if   [  "$id" -a "$json_type" = object ]; then
282     # if ! json="$(DB2 "$(UNSTRING "$json")" get "$id")"; then
283     if ! json="$(DB2 "$json" get "$id")"; then
284       debug "No key: \"$id\""
285       return 1
286     fi
287   elif [ "$idx" -a "$json_type" = array ]; then
288     if ! json="$(DB2 "$(UNSTRING "$json")" get @ "$(( idx + 1 ))")"; then
289     # if ! json="$(DB2 "$json" get @ "$(( idx + 1 ))")"; then
290       debug "No array index: \"$idx\""
291       return 1
292     fi
293   else
294     debug "Value type missmatch"
295     return 1
296   fi
297   json_get "$json" "$jpath"
298   return $?
299 }