Skip to content

Little fix for PR #6 #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions ReadMe.pod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
=pod

=for comment
DO NOT EDIT. This Pod was generated by Swim v0.1.41.
DO NOT EDIT. This Pod was generated by Swim v0.1.43.
See http://github.com/ingydotnet/swim-pm#readme

=encoding utf8
Expand Down Expand Up @@ -115,7 +115,7 @@ With no arguments, input is read from stdin. With one argument, input is taken
from the provided variable name. To use the internal cache, use C<-> as the
variable name. Output is always written to stdout.

=item C<< JSON.get [-a|-s|-b|-n|-z] <key-path> [<linear-var-name>] >>
=item C<< JSON.get [-a|-s|-b|-n|-z|-e] <key-path> [<linear-var-name>] >>

This function takes a key path and returns the corresponding value. If the key
is found, the exit status is 0, otherwise it is 1. If the value is a string,
Expand Down Expand Up @@ -194,6 +194,18 @@ successful return code.
The C<-z> flag on a C<JSON.get> will turn C<null> into the empty string, and
for a C<JSON.put> will turn any value into C<null>.

The C<-e> flag on a C<JSON.get> will return the values not in its raw form,
but pre-processed. Currently, the following two actions are supported:

=over

=item escaped double quotes are returned as non escaped,

=item escaped backslashes are returned as non escaped.


=back

=head1 Examples

# Load JSON to linear tree
Expand Down
8 changes: 7 additions & 1 deletion doc/json.swim
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ remove data from the linear form.
taken from the provided variable name. To use the internal cache, use `-` as
the variable name. Output is always written to stdout.

- `JSON.get [-a|-s|-b|-n|-z] <key-path> [<linear-var-name>]`
- `JSON.get [-a|-s|-b|-n|-z|-e] <key-path> [<linear-var-name>]`

This function takes a key path and returns the corresponding value. If the
key is found, the exit status is 0, otherwise it is 1. If the value is a
Expand Down Expand Up @@ -176,6 +176,12 @@ successful return code.
The `-z` flag on a `JSON.get` will turn `null` into the empty string, and for a
`JSON.put` will turn any value into `null`.

The `-e` flag on a `JSON.get` will return the values not in its raw form, but
pre-processed. Currently, the following two actions are supported:

- escaped double quotes are returned as non escaped,
- escaped backslashes are returned as non escaped.

= Examples

# Load JSON to linear tree
Expand Down
98 changes: 75 additions & 23 deletions lib/json.bash
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,58 @@ JSON.dump() {
}

JSON.get() {
local flag=""
if [[ $# -gt 0 && $1 =~ ^-([asnbz])$ ]]; then
flag="${BASH_REMATCH[1]}"
shift
local primary_flag
local secondary_flags
local json_source
local json_path

# At least the source to get the json should be defined.
if [[ $# -lt 1 ]]; then
JSON.die 'Usage: JSON.get [-a|-s|-n|-b|-z|-e] <key-path> [<tree-var>]'
fi
case $# in
1)
grep -Em1 "^$1 " | cut -f2 |
JSON.apply-get-flag "$flag"
;;
2)
if [[ $2 == '-' ]]; then
echo "$JSON__cache" |
grep -Em1 "^$1 " |
cut -f2 |
JSON.apply-get-flag "$flag"

# Let's see what flags there are.
for i in "${@}"; do

# Let's check if this is a flag, key-path or the tree-var.
if [[ $i =~ ^-([asnbze])$ ]]; then
case $i in
"-a" | "-s" | "-n" | "-b" | "-z")
primary_flag+="${i:1}"
;;
"-e" )
secondary_flags+="${i:1}"
;;
*)
# Unknown option.
;;
esac
else
if [[ ${#json_path} -eq 0 ]]; then
json_path=$i
elif [[ ${#json_source} -eq 0 ]]; then
json_source=$i
else
echo "${!2}" |
grep -Em1 "^$1 " |
cut -f2 |
JSON.apply-get-flag "$flag"
# Too may inputs?
JSON.die 'Usage: JSON.get [-a|-s|-n|-b|-z|-e] <key-path> [<tree-var>]'
fi
;;
*) JSON.die 'Usage: JSON.get [-a|-s|-n|-b|-z] <key-path> [<tree-var>]' ;;
esac
fi
done

# Primary flags should be only one!
if [[ ${#primary_flag} -gt 1 ]]; then
JSON.die 'Usage: JSON.get [-a|-s|-n|-b|-z|-e] <key-path> [<tree-var>]'
fi

if [[ $json_source = "-" ]]; then
json=$(echo "$JSON__cache" | grep -Em1 "^${json_path} " | cut -f2)
elif [[ ${#json_source} -gt 0 ]]; then
json=$(echo "${!json_source}" | grep -Em1 "^${json_path} " | cut -f2)
else
json=$(grep -Em1 "^${json_path} " | cut -f2)
fi

echo $json | JSON.apply-get-flag "$primary_flag" "$secondary_flags"
}

JSON.keys() {
Expand Down Expand Up @@ -235,13 +262,18 @@ JSON.parse-error() {

JSON.apply-get-flag() {
local value
local primary_flag=$1
local secondary_flags=$2

read -r value
# For now assume null can show up instead of string or number
if [[ $value == null ]]; then
echo ''
return 0
fi
case $1 in

# Dealing with first class actions.
case $primary_flag in
a)
[[ $value =~ ^$JSON_STR$ ]] && {
value="${value:1:$((${#value}-2))}"
Expand Down Expand Up @@ -276,6 +308,26 @@ JSON.apply-get-flag() {
;;
*) ;;
esac

# Dealing with second class actions.
# Note that there might be more than one secondary action.
IFS_OLD=$IFS
IFS=""
for i in ${secondary_flags}; do
case $i in
e)
# Expanding escaped characters currently is supported
# against quotes and backslashes.
value=$(echo $value | sed 's/\\"/"/g')
value=$(echo $value | sed 's/\\\\/\\/g')
;;
*)
# Do nothing.
;;
esac
done
IFS=$IFS_OLD

echo "$value"
return 0
}
Expand Down
18 changes: 13 additions & 5 deletions man/man1/json.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
.\"
.\" Standard preamble:
.\" ========================================================================
Expand Down Expand Up @@ -71,7 +71,7 @@
.\" ========================================================================
.\"
.IX Title "\&\s-1JSON 1"
.TH \&\s-1JSON 1 "January 2016" "Generated by Swim v0.1.41" "JSON\s0 for Bash"
.TH \&\s-1JSON 1 "March 2016" "Generated by Swim v0.1.43" "JSON\s0 for Bash"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
Expand Down Expand Up @@ -170,9 +170,9 @@ With no arguments, input is read from stdin and output is written to stdout. Wit
This function takes a linear tree as input and generates \s-1JSON\s0 as output.
.Sp
With no arguments, input is read from stdin. With one argument, input is taken from the provided variable name. To use the internal cache, use \f(CW\*(C`\-\*(C'\fR as the variable name. Output is always written to stdout.
.ie n .IP """JSON.get [\-a|\-s|\-b|\-n|\-z] <key\-path> [<linear\-var\-name>]""" 4
.el .IP "\f(CWJSON.get [\-a|\-s|\-b|\-n|\-z] <key\-path> [<linear\-var\-name>]\fR" 4
.IX Item "JSON.get [-a|-s|-b|-n|-z] <key-path> [<linear-var-name>]"
.ie n .IP """JSON.get [\-a|\-s|\-b|\-n|\-z|\-e] <key\-path> [<linear\-var\-name>]""" 4
.el .IP "\f(CWJSON.get [\-a|\-s|\-b|\-n|\-z|\-e] <key\-path> [<linear\-var\-name>]\fR" 4
.IX Item "JSON.get [-a|-s|-b|-n|-z|-e] <key-path> [<linear-var-name>]"
This function takes a key path and returns the corresponding value. If the key is found, the exit status is 0, otherwise it is 1. If the value is a string, it will be enclosed in double quotes. Otherwise it will be a number or the unquoted strings: \f(CW\*(C`true\*(C'\fR, \f(CW\*(C`false\*(C'\fR or \f(CW\*(C`null\*(C'\fR.
.Sp
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.
Expand Down Expand Up @@ -219,6 +219,14 @@ The \f(CW\*(C`\-n\*(C'\fR flag requires no value transformation, but it will cau
If \f(CW\*(C`\-b\*(C'\fR is used for a \f(CW\*(C`JSON.get\*(C'\fR, true will become 0 and false will become 1. \f(CW\*(C`JSON.put\*(C'\fR will do the reverse. This follows Bash's idea of using 0 for a successful return code.
.PP
The \f(CW\*(C`\-z\*(C'\fR flag on a \f(CW\*(C`JSON.get\*(C'\fR will turn \f(CW\*(C`null\*(C'\fR into the empty string, and for a \f(CW\*(C`JSON.put\*(C'\fR will turn any value into \f(CW\*(C`null\*(C'\fR.
.PP
The \f(CW\*(C`\-e\*(C'\fR flag on a \f(CW\*(C`JSON.get\*(C'\fR will return the values not in its raw form, but pre-processed. Currently, the following two actions are supported:
.IP "escaped double quotes are returned as non escaped," 4
.IX Item "escaped double quotes are returned as non escaped,"
.PD 0
.IP "escaped backslashes are returned as non escaped." 4
.IX Item "escaped backslashes are returned as non escaped."
.PD
.SH "Examples"
.IX Header "Examples"
.Vb 4
Expand Down
167 changes: 167 additions & 0 deletions test/arrays.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env bash

source test/setup

# Number denotes how many tests are to be executed.
use Test::More tests 45
use JSON

# Testing json where an array element is not the first or the last one.
# Check test/arrays1.json.
# ------------------------------------------------------------------------------

# 1.1. Does it load?
tree=$(cat test/arrays1.json | JSON.load)
ok $? "JSON.load succeeded"

# 1.2. Does it fetch first element being non-array?
is "$(JSON.get '/id' tree)" '"20150817"' "JSON.get works on first element."

# 1.3. Escaped quotes?
is "$(JSON.get -s '/_etag' tree)" '\"0300e163-0000-0000-0000-55d223bd0000\"' "JSON.get works on escaped quotes"

# 1.4. Escaped quotes?
is "$(JSON.get -s -e '/_etag' tree)" '"0300e163-0000-0000-0000-55d223bd0000"' "JSON.get works on escaped quotes"

# 1.5. Escaped quotes?
is "$(JSON.get -e '/_etag' tree)" '""0300e163-0000-0000-0000-55d223bd0000""' "JSON.get works on escaped quotes"

# 1.6. Retrieving the first array element.
is "$(JSON.get '/osList' tree)" '' "JSON.get works on first array element."

# 1.7. Retrieving a simple value of an element of the first array element.
is "$(JSON.get '/osList/1/osName' tree)" '"Mac"' "JSON.get works on a simple value of an element of the first array element."

# 1.8. Retrieving an array element of an element of the first array element.
is "$(JSON.get '/osList/1/softwareList' tree)" '' "JSON.get works on an array element of an element of the first array element."

# 1.9. Retrieving a simple value of an element of an array of an element of element of the first array element.
is "$(JSON.get '/osList/1/softwareList/1/softwareName' tree)" '"VirtualBox"' "JSON.get works on a simple value of an element of an array of an element of element of the first array element."

# Testing json where an array element is the first element.
# Check test/arrays2.json.
# ------------------------------------------------------------------------------

# 2.1. Does it load?
tree=$(cat test/arrays1.json | JSON.load)
ok $? "JSON.load succeeded"

# 2.2. Does it fetch first element being non-array?
is "$(JSON.get '/id' tree)" '"20150817"' "JSON.get works on first element."

# 2.3. Escaped quotes?
is "$(JSON.get -s '/_etag' tree)" '\"0300e163-0000-0000-0000-55d223bd0000\"' "JSON.get works on escaped quotes"

# 2.4. Escaped quotes?
is "$(JSON.get -s -e '/_etag' tree)" '"0300e163-0000-0000-0000-55d223bd0000"' "JSON.get works on escaped quotes"

# 2.5. Escaped quotes?
is "$(JSON.get -e '/_etag' tree)" '""0300e163-0000-0000-0000-55d223bd0000""' "JSON.get works on escaped quotes"

# 2.6. Retrieving the first array element.
is "$(JSON.get '/osList' tree)" '' "JSON.get works on first array element."

# 2.7. Retrieving a simple value of an element of the first array element.
is "$(JSON.get '/osList/1/osName' tree)" '"Mac"' "JSON.get works on a simple value of an element of the first array element."

# 2.8. Retrieving an array element of an element of the first array element.
is "$(JSON.get '/osList/1/softwareList' tree)" '' "JSON.get works on an array element of an element of the first array element."

# 2.9. Retrieving a simple value of an element of an array of an element of element of the first array element.
is "$(JSON.get '/osList/1/softwareList/1/softwareName' tree)" '"VirtualBox"' "JSON.get works on a simple value of an element of an array of an element of element of the first array element."

# Testing json where an array element is the last element.
# Check test/arrays3.json.
# ------------------------------------------------------------------------------

# 3.1. Does it load?
tree=$(cat test/arrays1.json | JSON.load)
ok $? "JSON.load succeeded"

# 3.2. Does it fetch first element being non-array?
is "$(JSON.get '/id' tree)" '"20150817"' "JSON.get works on first element."

# 3.3. Escaped quotes?
is "$(JSON.get -s '/_etag' tree)" '\"0300e163-0000-0000-0000-55d223bd0000\"' "JSON.get works on escaped quotes"

# 3.4. Escaped quotes?
is "$(JSON.get -s -e '/_etag' tree)" '"0300e163-0000-0000-0000-55d223bd0000"' "JSON.get works on escaped quotes"

# 3.5. Escaped quotes?
is "$(JSON.get -e '/_etag' tree)" '""0300e163-0000-0000-0000-55d223bd0000""' "JSON.get works on escaped quotes"

# 3.6. Retrieving the first array element.
is "$(JSON.get '/osList' tree)" '' "JSON.get works on first array element."

# 3.7. Retrieving a simple value of an element of the first array element.
is "$(JSON.get '/osList/1/osName' tree)" '"Mac"' "JSON.get works on a simple value of an element of the first array element."

# 3.8. Retrieving an array element of an element of the first array element.
is "$(JSON.get '/osList/1/softwareList' tree)" '' "JSON.get works on an array element of an element of the first array element."

# 3.9. Retrieving a simple value of an element of an array of an element of element of the first array element.
is "$(JSON.get '/osList/1/softwareList/1/softwareName' tree)" '"VirtualBox"' "JSON.get works on a simple value of an element of an array of an element of element of the first array element."

# Testing json where an array element is the first and the last element only.
# Check test/arrays4.json.
# ------------------------------------------------------------------------------

# 4.1. Does it load?
tree=$(cat test/arrays1.json | JSON.load)
ok $? "JSON.load succeeded"

# 4.2. Does it fetch first element being non-array?
is "$(JSON.get '/id' tree)" '"20150817"' "JSON.get works on first element."

# 4.3. Escaped quotes?
is "$(JSON.get -s '/_etag' tree)" '\"0300e163-0000-0000-0000-55d223bd0000\"' "JSON.get works on escaped quotes"

# 4.4. Escaped quotes?
is "$(JSON.get -s -e '/_etag' tree)" '"0300e163-0000-0000-0000-55d223bd0000"' "JSON.get works on escaped quotes"

# 4.5. Escaped quotes?
is "$(JSON.get -e '/_etag' tree)" '""0300e163-0000-0000-0000-55d223bd0000""' "JSON.get works on escaped quotes"

# 4.6. Retrieving the first array element.
is "$(JSON.get '/osList' tree)" '' "JSON.get works on first array element."

# 4.7. Retrieving a simple value of an element of the first array element.
is "$(JSON.get '/osList/1/osName' tree)" '"Mac"' "JSON.get works on a simple value of an element of the first array element."

# 4.8. Retrieving an array element of an element of the first array element.
is "$(JSON.get '/osList/1/softwareList' tree)" '' "JSON.get works on an array element of an element of the first array element."

# 4.9. Retrieving a simple value of an element of an array of an element of element of the first array element.
is "$(JSON.get '/osList/1/softwareList/1/softwareName' tree)" '"VirtualBox"' "JSON.get works on a simple value of an element of an array of an element of element of the first array element."

# Testing json where an array element is the first, the last element and more exist.
# Check test/arrays5.json.
# ------------------------------------------------------------------------------

# 5.1. Does it load?
tree=$(cat test/arrays1.json | JSON.load)
ok $? "JSON.load succeeded"

# 5.2. Does it fetch first element being non-array?
is "$(JSON.get '/id' tree)" '"20150817"' "JSON.get works on first element."

# 5.3. Escaped quotes?
is "$(JSON.get -s '/_etag' tree)" '\"0300e163-0000-0000-0000-55d223bd0000\"' "JSON.get works on escaped quotes"

# 5.4. Escaped quotes?
is "$(JSON.get -s -e '/_etag' tree)" '"0300e163-0000-0000-0000-55d223bd0000"' "JSON.get works on escaped quotes"

# 5.5. Escaped quotes?
is "$(JSON.get -e '/_etag' tree)" '""0300e163-0000-0000-0000-55d223bd0000""' "JSON.get works on escaped quotes"

# 5.6. Retrieving the first array element.
is "$(JSON.get '/osList' tree)" '' "JSON.get works on first array element."

# 5.7. Retrieving a simple value of an element of the first array element.
is "$(JSON.get '/osList/1/osName' tree)" '"Mac"' "JSON.get works on a simple value of an element of the first array element."

# 5.8. Retrieving an array element of an element of the first array element.
is "$(JSON.get '/osList/1/softwareList' tree)" '' "JSON.get works on an array element of an element of the first array element."

# 5.9. Retrieving a simple value of an element of an array of an element of element of the first array element.
is "$(JSON.get '/osList/1/softwareList/1/softwareName' tree)" '"VirtualBox"' "JSON.get works on a simple value of an element of an array of an element of element of the first array element."
Loading