# along with this program. If not, see <https://www.gnu.org/licenses/>.
__init() {
- if ! include "log"; then
+ if ! include "log" "is" "array"; then
return 1
fi
+ declare -gxir __json_type_integer=0
+ declare -gxir __json_type_string=1
+ declare -gxir __json_type_bool=2
+ declare -gxir __json_type_float=3
+ declare -gxir __json_type_object=4
+ declare -gxir __json_type_array=5
+
return 0
}
-json_object() {
- local args=("$@")
+_json_guess_type() {
+ local input="$1"
+
+ local re_number
+ local re_float
+ local re_object
+ local re_array
+
+ re_number='^[-+]{,1}[0-9]+$'
+ re_float='^[-+]{,1}([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)$'
+ re_object='^\{.*\}$'
+ re_array='^\[.*\]$'
+
+ if [[ "$input" =~ $re_number ]]; then
+ echo "$__json_type_integer"
+
+ elif [[ "$input" =~ $re_object ]]; then
+ echo "$__json_type_object"
- local i
- local nvps
+ elif [[ "$input" =~ $re_array ]]; then
+ echo "$__json_type_array"
+
+ elif [[ "$input" =~ $re_float ]]; then
+ echo "$__json_type_float"
+
+ elif [[ "$input" == "true" ]] ||
+ [[ "$input" == "false" ]]; then
+ echo "$__json_type_bool"
+
+ else
+ echo "$__json_type_string"
+ fi
+
+ return 0
+}
+
+_json_get_type() {
+ local input="$1"
+
+ declare -A type_map
+ local type_prefix
+ local type
+ local output
+
+ type_map["s:"]="$__json_type_string"
+ type_map["i:"]="$__json_type_integer"
+ type_map["b:"]="$__json_type_bool"
+ type_map["f:"]="$__json_type_float"
+ type_map["o:"]="$__json_type_object"
+ type_map["a:"]="$__json_type_array"
+
+ type_prefix="${input:0:2}"
+
+ if array_contains "$type_prefix" "${!type_map[@]}"; then
+ type="${type_map[$type_prefix]}"
+ output="${input:2}"
+ else
+ type=$(_json_guess_type "$input")
+ output="$input"
+ fi
+
+ echo "$output"
+ return "$type"
+}
- nvps=0
+_json_print_value() {
+ local value="$1"
+
+ local value_raw
+ local output
+
+ value_raw=$(_json_get_type "$value")
+ case "$?" in
+ "$__json_type_integer")
+ if ! output=$(printf '%d' "$value_raw"); then
+ return 1
+ fi
+ ;;
+
+ "$__json_type_float")
+ if ! output=$(printf '%f' "$value_raw"); then
+ return 1
+ fi
+ ;;
+
+ "$__json_type_bool"|"$__json_type_object"|"$__json_type_array")
+ if ! output=$(printf '%s' "$value_raw"); then
+ return 1
+ fi
+ ;;
+
+ "$__json_type_string")
+ if ! output=$(printf '"%s"' "$value_raw"); then
+ return 1
+ fi
+ ;;
+
+ *)
+ return 1
+ ;;
+ esac
+
+ echo "$output"
+ return 0
+}
- if (( ${#args[@]} % 2 != 0 )); then
- log_error "Invalid number of arguments"
- return 1
- fi
+json_object() {
+ local args=("$@")
- printf "{"
- for (( i = 0; i < ${#args[@]}; i++ )); do
- local name
- local value
+ local i
+ local nvps
+ local output
- local re_number
- local re_object
- local re_array
+ nvps=0
+ output="{"
- re_number='^[0-9]+$'
- re_object='^\{.*\}$'
- re_array='^\[.*\]$'
+ if (( ${#args[@]} % 2 != 0 )); then
+ log_error "Invalid number of arguments"
+ return 1
+ fi
- name="${args[$i]}"
- ((i++))
- value="${args[$i]}"
+ for (( i = 0; i < ${#args[@]}; i++ )); do
+ local name
+ local value
+ local value_raw
- if [ -z "$name" ] || [ -z "$value" ]; then
- continue
- fi
+ name="${args[$i]}"
+ ((i++))
+ value="${args[$i]}"
- if (( nvps > 0 )); then
- printf ', '
- fi
+ if [ -z "$name" ] || [ -z "$value" ]; then
+ continue
+ fi
- if [[ "$value" =~ $re_number ]]; then
- printf '"%s": %d' "$name" "$value"
+ if (( nvps > 0 )); then
+ output+=", "
+ fi
- elif [[ "$value" =~ $re_object ]] ||
- [[ "$value" =~ $re_array ]]; then
- printf '"%s": %s' "$name" "$value"
+ if ! value_raw=$(_json_print_value "$value"); then
+ return 1
+ fi
- else
- printf '"%s": "%s"' "$name" "$value"
- fi
+ if ! output+=$(printf '"%s": %s' "$name" "$value_raw"); then
+ return 1
+ fi
- ((nvps++))
- done
- printf "}\n"
+ ((nvps++))
+ done
+ output+="}"
- return 0
+ printf "%s\n" "$output"
+ return 0
}
json_object_get() {
json_array() {
local args=("$@")
+ local output
local arg
local n
- local re_number
- local re_object
- local re_array
-
- re_number='^[0-9]+$'
- re_object='^\{.*\}$'
- re_array='^\[.*\]$'
-
- printf "["
+ output="["
n=0
for arg in "${args[@]}"; do
fi
if (( n > 0 )); then
- printf ", "
+ output+=", "
fi
- if [[ "$arg" =~ $re_number ]]; then
- printf '%d' "$arg"
-
- elif [[ "$arg" =~ $re_object ]] ||
- [[ "$arg" =~ $re_array ]]; then
- printf '%s' "$arg"
-
- else
- printf '"%s"' "$arg"
+ if ! output+=$(_json_print_value "$arg"); then
+ return 1
fi
((n++))
done
- printf "]\n"
+ output+="]"
+
+ printf "%s\n" "$output"
return 0
}