Skip to content

Commit 890c87d

Browse files
committed
implement JSON.object and JSON.keys
1 parent 710cfa6 commit 890c87d

File tree

6 files changed

+109
-0
lines changed

6 files changed

+109
-0
lines changed

ReadMe.pod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ cache). The value (if any) is written to stdout.
128128

129129
See FLAGS below for an explanation of the flag options.
130130

131+
=item C<< JSON.keys <key-path> [<linear-var-name>] >>
132+
133+
This function takes a key path and returns the keys of the corresponding
134+
object, one per line. If the key is not found or the value of the key is not
135+
an object, it will return nothing.
136+
137+
=item C<< JSON.object <key-path> [<linear-var-name>] >>
138+
139+
This function takes a key path and returns the corresponding object. If the
140+
key is not found, it will return nothing.
141+
131142
=item C<< JSON.put [-s|-b|-n|-z] <key-path> <new-value> [<linear-var-name>] >>
132143

133144
This function adds a path/value pair to the linear tree. If the path already

doc/json.swim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ remove data from the linear form.
112112

113113
See FLAGS below for an explanation of the flag options.
114114

115+
- `JSON.keys <key-path> [<linear-var-name>]`
116+
117+
This function takes a key path and returns the keys of the corresponding
118+
object, one per line. If the key is not found or the value of the
119+
key is not an object, it will return nothing.
120+
121+
- `JSON.object <key-path> [<linear-var-name>]`
122+
123+
This function takes a key path and returns the corresponding object.
124+
If the key is not found, it will return nothing.
125+
115126
- `JSON.put [-s|-b|-n|-z] <key-path> <new-value> [<linear-var-name>]`
116127

117128
This function adds a path/value pair to the linear tree. If the path already

lib/json.bash

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,44 @@ JSON.get() {
6868
esac
6969
}
7070

71+
JSON.keys() {
72+
if [[ $# -gt 2 ]]; then
73+
JSON.die 'Usage: JSON.keys <key-path> [<tree-var>]'
74+
fi
75+
JSON.object "$@" |
76+
cut -f1 |
77+
sed "s/^\///; s/\/.*//" |
78+
sort -u
79+
}
80+
81+
JSON.object() {
82+
case $# in
83+
1)
84+
JSON._object "$@"
85+
;;
86+
2)
87+
if [ "$2" == '-' ]; then
88+
echo "$JSON__cache" | JSON._object "$@"
89+
else
90+
echo "${!2}" | JSON._object "$@"
91+
fi
92+
;;
93+
*)
94+
JSON.die 'Usage: JSON.object <key-path> [<tree-var>]' ;;
95+
esac
96+
}
97+
98+
JSON._object() {
99+
local key=$1
100+
if [[ -n $key && $key != "/" ]]; then
101+
key=${key/\//\\/}
102+
grep -E "^$key/" |
103+
sed "s/^$key//"
104+
else
105+
cat
106+
fi
107+
}
108+
71109
JSON.put() {
72110
set -o pipefail
73111
if [[ $# -gt 0 && $1 =~ ^-([snbz])$ ]]; then

man/man1/json.1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ This function takes a key path and returns the corresponding value. If the key i
178178
With just the one required argument, the linear tree will be obtained from stdin. Otherwise it can be provided with a variable name (or \f(CW\*(C`\-\*(C'\fR for the cache). The value (if any) is written to stdout.
179179
.Sp
180180
See \s-1FLAGS\s0 below for an explanation of the flag options.
181+
.ie n .IP """JSON.keys <key\-path> [<linear\-var\-name>]""" 4
182+
.el .IP "\f(CWJSON.keys <key\-path> [<linear\-var\-name>]\fR" 4
183+
.IX Item "JSON.keys <key-path> [<linear-var-name>]"
184+
This function takes a key path and returns the keys of the corresponding object, one per line. If the key is not found or the value of the key is not an object, it will return nothing.
185+
.ie n .IP """JSON.object <key\-path> [<linear\-var\-name>]""" 4
186+
.el .IP "\f(CWJSON.object <key\-path> [<linear\-var\-name>]\fR" 4
187+
.IX Item "JSON.object <key-path> [<linear-var-name>]"
188+
This function takes a key path and returns the corresponding object. If the key is not found, it will return nothing.
181189
.ie n .IP """JSON.put [\-s|\-b|\-n|\-z] <key\-path> <new\-value> [<linear\-var\-name>]""" 4
182190
.el .IP "\f(CWJSON.put [\-s|\-b|\-n|\-z] <key\-path> <new\-value> [<linear\-var\-name>]\fR" 4
183191
.IX Item "JSON.put [-s|-b|-n|-z] <key-path> <new-value> [<linear-var-name>]"

test/keys.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"description": "description of gist",
3+
"files": {
4+
"file1.txt": {
5+
"type": "text/plain",
6+
"content": "two\nlines"
7+
},
8+
"file 2.txt": {
9+
"type": "text/plain",
10+
"content": "two\nlines"
11+
}
12+
13+
}
14+
}

test/keys.t

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
source test/setup
4+
5+
use Test::More tests 5
6+
use JSON
7+
8+
tree1=$(cat test/keys.json | JSON.load)
9+
ok $? "JSON.load succeeded"
10+
11+
is "$(JSON.get '/files/file 2.txt/type' tree1)" '"text/plain"' \
12+
"JSON.get works"
13+
14+
file_object=$(JSON.object '/files' tree1)
15+
16+
keys="$(JSON.keys '/' file_object)"
17+
18+
is "$keys" "file1.txt"$'\n'"file 2.txt" \
19+
"JSON.keys '/'"
20+
21+
keys="$(JSON.keys '/files' tree1)"
22+
is "$keys" "file1.txt"$'\n'"file 2.txt" \
23+
"JSON.keys 'files'"
24+
25+
keys="$(JSON.keys '/' tree1)"
26+
is "$keys" "description"$'\n'"files" \
27+
"JSON.keys ''"

0 commit comments

Comments
 (0)