Last active
June 21, 2018 22:43
-
-
Save djfdyuruiry/6b05ef720b59ff1eb8782e6e92faeac2 to your computer and use it in GitHub Desktop.
JSON path bash util function using python, supports array queries, array indices, list object fields and array length query.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
jsonLoadFromStdIn="json.load(sys.stdin)" | |
loopOverItems=false | |
loopJsonOperation="" | |
__doJsonOperation() { | |
json="$1" | |
operation="$2" | |
operationWithJsonLoad=${operation/__JSON__/$jsonLoadFromStdIn} | |
echo "${json}" | python -c "import sys, json; print ${operationWithJsonLoad}" | |
} | |
__convertJsonPathToOperation() { | |
jsonPath="$1" | |
jsonPath="${jsonPath:1}" | |
jsonPath="${jsonPath//[/.[}" | |
IFS='.' read -ra jsonPathParts <<< "${jsonPath}" | |
loopOverItems=false | |
loopJsonOperation="" | |
jsonOperation="__JSON__" | |
for jsonPathPart in "${jsonPathParts[@]}"; do | |
if [ "${jsonPathPart:0:1}" = "[" ] && [ "${jsonPathPart: -1}" = "]" ]; then | |
# handle array lookups | |
if [ "${jsonPathPart}" = "[*]" ]; then | |
# act on all items in array | |
loopOverItems=true | |
else | |
# get item at index in array | |
if [ "${loopOverItems}" = false ]; then | |
jsonOperation="${jsonOperation}${jsonPathPart}" | |
else | |
loopJsonOperation="${loopJsonOperation}${jsonPathPart}" | |
fi | |
fi | |
elif [ "${jsonPathPart}" = "length()" ]; then | |
# get length of array | |
if [ "${loopOverItems}" = false ]; then | |
jsonOperation="len(${jsonOperation})" | |
else | |
loopJsonOperation="${loopJsonOperation}.__len__()" | |
fi | |
elif [ "${jsonPathPart}" = "fields()" ]; then | |
# get fields in object | |
if [ "${loopOverItems}" = false ]; then | |
loopOverItems=true | |
jsonOperation="${jsonOperation}.keys()" | |
else | |
loopJsonOperation="${loopJsonOperation}.keys()" | |
fi | |
elif [ ! -z "${jsonPathPart}" ]; then | |
# get object property | |
if [ "${loopOverItems}" = false ]; then | |
jsonOperation="${jsonOperation}['${jsonPathPart}']" | |
else | |
loopJsonOperation="['${loopJsonOperation}${jsonPathPart}']" | |
fi | |
fi | |
done | |
echo "jsonOperation=\"${jsonOperation}\"; loopOverItems=${loopOverItems}; loopJsonOperation=\"${loopJsonOperation}\"" | |
} | |
json-path-query() { | |
json="$1" | |
jsonPath="$2" | |
if [ -z "${json}" ] || [ -z "${jsonPath}" ]; then | |
>&2 echo "Usage: $0 json jsonPath" | |
return 1 | |
fi | |
eval $(__convertJsonPathToOperation "${jsonPath}") | |
if [ "${loopOverItems}" = false ]; then | |
__doJsonOperation "${json}" "${jsonOperation}" | |
return 0 | |
fi | |
isDictionary="$(__doJsonOperation "${json}" "isinstance(${jsonOperation}, dict)" | tr '[:upper:]' '[:lower:]')" | |
numItems="$(__doJsonOperation "${json}" "len(${jsonOperation})")" | |
if [ "${isDictionary}" = true ]; then | |
jsonOperation="list(${jsonOperation}.values())" | |
fi | |
for ((i=0; i < ${numItems}; i++)); do | |
__doJsonOperation "${json}" "${jsonOperation}[${i}]${loopJsonOperation}" | |
done | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment