Skip to content

Commit

Permalink
json->parse_json, add query_json
Browse files Browse the repository at this point in the history
  • Loading branch information
dubiousjim committed May 6, 2012
1 parent d6cb8b8 commit 72b1557
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 2 deletions.
39 changes: 38 additions & 1 deletion README.lib
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ delete_quoted(str, [repl=""])
Optionally permits substituting a different replacement string (rather than "").


json(str, T, V, [slack=""])
parse_json(str, T, V, [slack=""])
Parses JSON str. A successful parse will fill the T and V arrays like this:

parse of: {"one": 10, "two": [20,30,[40,[50,60]]], "three": {}}
Expand Down Expand Up @@ -317,6 +317,43 @@ a return value < 1.
they conform to JavaScript identifier syntax.


query_json(str, A, [root, [slack]])
Parses JSON str with supplied slack, if any. Unpacks the returned object or
array into A. Optionally permits specifying a different root to unpack.
Example:

query of: {"one": 1, "two": {"alpha":0, "beta": {"uno": { "id":1, "child": {
"legal": true, "id": 11 }}, "dos": {"id": 2, "child": {"legal": true,
"id": 21 }}}}}
with root="two.beta"

A["uno","id"] = 1
A["uno","child", "legal"] = 1
A["uno","child", "id"] = 11
A["dos","id"] = 2
A["dos","child", "legal"] = 1
A["dos","child", "id"] = 21

Arrays are handled like this:

query of: {"one": 1, "two": {"alpha":0, "beta": {"uno": { "id":[1,101,1001], "child": {
"legal": true, "id": [11,-11] }}, "dos": {"id": 2, "child": {"legal": true,
"id": 21 }}}}}
with root="two.beta"

A["uno","id", 0] = 3
A["uno","id", 1] = 1
A["uno","id", 2] = 101
A["uno","id", 3] = 1001
A["uno","child", "legal"] = 1
A["uno","child", "id", 0] = 2
A["uno","child", "id", 1] = 11
A["uno","child", "id", 2] = -11
A["dos","id"] = 2
A["dos","child", "legal"] = 1
A["dos","child", "id"] = 21


rep(str, n, [sep=""])
Returns the concatenation of n copies of str, optionally joined by sep.

Expand Down
65 changes: 64 additions & 1 deletion library.awk
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ function delete_quoted(str, repl) {
}


function json(str, T, V, slack, c,s,n,a,A,b,B,C,U,W,i,j,k,u,v,w,root) {
function parse_json(str, T, V, slack, c,s,n,a,A,b,B,C,U,W,i,j,k,u,v,w,root) {
# use strings, numbers, booleans as separators
# c = "[^\"\\\\[:cntrl:]]|\\\\[\"\\\\/bfnrt]|\\u[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]"
c = "[^\"\\\\\001-\037]|\\\\[\"\\\\/bfnrt]|\\\\u[[:xdigit:]A-F][[:xdigit:]A-F][[:xdigit:]A-F][[:xdigit:]A-F]"
Expand Down Expand Up @@ -699,6 +699,69 @@ function json(str, T, V, slack, c,s,n,a,A,b,B,C,U,W,i,j,k,u,v,w,root) {
}


function query_json(str, X, root, slack, T, V, A, B, C, i, j, k) {
k = parse_json(str, T, V, slack)
if (k < 1) return k
split(root, C, ".")
j = 1
while (j in C) {
if (T[k] == "array")
split(V[k], A, ",")
else {
split("", A)
asplit(V[k], B, ":", ",")
for (i in B)
A[V[i]] = B[i]
}
if (C[j] in A) {
k = A[C[j]]
j++
} else return -11 # can't find requested root
}
# split("", B)
# split("", C)
B[k] = ""
C[k] = 0
C[0] = k
do {
C[0] = C[k]
delete C[k]
j = T[k]
if (j == "array") {
j = split(V[k], A, ",")
k = B[k] ? B[k] SUBSEP : ""
X[k 0] = j
for (i=1; i<=j; i++) {
# push A[i] to C, (B[k],i) to B
C[A[i]] = C[0]
B[A[i]] = k i
C[0] = A[i]
}
} else if (j == "object") {
asplit(V[k], A, ":", ",")
k = B[k] ? B[k] SUBSEP : ""
for (i in A) {
# push A[i] to C, (B[k],V[i]) to B
C[A[i]] = C[0]
B[A[i]] = k V[i]
C[0] = A[i]
}
} else if (j == "number") {
X[B[k]] = V[k]
} else if (j == "true") {
X[B[k]] = 1
} else if (j == "false") {
X[B[k]] = 0
} else {
# null will satisfy ismissing()
X[B[k]]
}
k = C[0]
} while (k)
return 0
}


# repeat str n times, from http://awk.freeshell.org/RepeatAString
function rep(str, n, sep, remain, result) {
if (n < 2) {
Expand Down

0 comments on commit 72b1557

Please sign in to comment.