Skip to content

Instantly share code, notes, and snippets.

@budhash
Forked from mohd-akram/json.awk
Created July 1, 2025 22:24
Show Gist options
  • Save budhash/79c12453c641985e5dba8765a4792ab9 to your computer and use it in GitHub Desktop.
Save budhash/79c12453c641985e5dba8765a4792ab9 to your computer and use it in GitHub Desktop.
Extract a value from a JSON object or array in awk
#
# Extract a JSON value in an object:
#
# items = get_json_value(json, "payload.tree.items")
#
# Or in an array:
#
# while ((item = get_json_value(items, i++)))
# name = decode_json_string(get_json_value(item, "name"))
#
# Or both:
#
# item = get_json_value(json, "payload.tree.items.0")
#
function get_json_value(s, key, type, all, rest, nested, isval, i, c, k) {
type = substr(s, 1, 1)
if (type != "{" && type != "[") error("invalid json array/object " s)
all = key == "" && key == 0
if (!all && (i = index(key, "."))) {
rest = substr(key, i+1)
key = substr(key, 1, i-1)
nested = 1
}
if (type == "[") k = 0
isval = type == "["
for (i = 2; i < length(s); i += length(c)) {
c = substr(s, i, 1)
if (c == "\"") {
if (!match(substr(s, i), /^"(\\.|[^\\"])*"/))
error("invalid json string " substr(s, i))
c = substr(s, i, RLENGTH)
if (!isval) k = substr(c, 2, length(c)-2)
}
else if (c == "{" || c == "[") {
c = (!all && k == key && nested) ? \
get_json_value(substr(s, i), rest) : \
get_json_value(substr(s, i))
}
else if (c == "}" || c == "]") break
else if (c == ",") isval = type == "["
else if (c == ":") ;
else if (c ~ /[[:space:]]/) continue
else {
if (!match(substr(s, i), /[]},[:space:]]/))
error("invalid json value " substr(s, i))
c = substr(s, i, RSTART-1)
}
if (!all && k == key && isval) {
if (nested && substr(s, i, 1) !~ /[[{]/) return
return c
}
if (type == "{" && c == ":") isval = 1
if (type == "[" && c == ",") ++k
}
if (all) return substr(s, 1, i)
}
function decode_json_string(s, out, esc) {
if (s !~ /^"./ || substr(s, length(s), 1) != "\"")
error("invalid json string " s)
s = substr(s, 2, length(s)-2)
esc["b"] = "\b"; esc["f"] = "\f"; esc["n"] = "\n"; esc["\""] = "\""
esc["r"] = "\r"; esc["t"] = "\t"; esc["/"] = "/" ; esc["\\"] = "\\"
while (match(s, /\\/)) {
if (!(substr(s, RSTART+1, 1) in esc))
error("unknown json escape " substr(s, RSTART, 2))
out = out substr(s, 1, RSTART-1) esc[substr(s, RSTART+1, 1)]
s = substr(s, RSTART+2)
}
return out s
}
function error(msg) {
printf "%s: %s\n", ARGV[0], msg > "/dev/stderr"
exit 1
}
#
# Example usage
#
# $ curl https://httpbin.org/json | awk -f json.awk slideshow.title
# "Sample Slide Show"
#
BEGIN {
while (ret = getline l < "/dev/stdin") {
if (ret == -1) error("getline error")
s = s l
}
print get_json_value(s, ARGV[1])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment