# # Extract a JSON value in an object or array: # # name = decode_json_string(get_json_value(json, "author.name")) # date = decode_json_string(get_json_value(json, "events.0.date")) # # Or an entire object: # # get_json_value(json, "dependencies", deps) # # for (name in deps) # version = decode_json_string(deps[name]) # # Or array: # # get_json_value(json, "payload.tree.items", items) # # for (i = 0; items[i]; i++) { # get_json_value(items[i], null, item) # type = decode_json_string(item["type"]) # name = decode_json_string(item["name"]) # } # function get_json_value( \ s, key, a, skip, type, all, rest, isval, i, c, k, null \ ) { if (match(s, /^[[:space:]]+/)) s = substr(s, RLENGTH+1) type = substr(s, 1, 1) all = key == "" && key == 0 if (type != "{" && type != "[") { if (!all) error("invalid json array/object " s) if (!match(s, /^(null|true|false|"(\\.|[^\\"])*"|[.0-9Ee+-]+)/)) error("invalid json value " s) return substr(s, 1, RLENGTH) } if (!all && (i = index(key, "."))) { rest = substr(key, i+1) key = substr(key, 1, i-1) } if ((isval = type == "[")) k = 0 for (i = 2; i <= length(s); i += length(c)) { if (match(substr(s, i), /^[[:space:]]+/)) { c = substr(s, i, RLENGTH) continue } c = substr(s, i, 1) if (c == "}" || c == "]") break else if (c == ",") { if ((isval = type == "[")) ++k } else if (c == ":") isval = 1 else { if (!all && k == key && isval) return get_json_value(substr(s, i), rest, a) c = get_json_value(substr(s, i), null, null, 1) if (all && !skip && isval) a[k] = c if (c ~ /^"/ && !isval) k = substr(c, 2, length(c)-2) } } if ((type == "{" && c != "}") || (type == "[" && c != "]")) error("unterminated json array/object " s) 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 "\n" } print get_json_value(s, ARGV[1]) }