From 33b98477bf06a1dac9ed6639c651e24519ca5170 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Thu, 25 Jun 2026 19:18:13 +0530 Subject: [PATCH] feat: Added a custom json extractor --- lib/json.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 lib/json.sh diff --git a/lib/json.sh b/lib/json.sh new file mode 100644 index 0000000..4370582 --- /dev/null +++ b/lib/json.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# generic JSON parser in pure bash and awk. +# reads JSON from stdin and outputs a flattened list of key-value pairs. +# example input: {"plugins": {"my_plugin": {"version": "1.0", "arr": [1, 2]}}} +# example output: + # plugins.my_plugin.version="1.0" + # plugins.my_plugin.arr[0]=1 + # plugins.my_plugin.arr[1]=2 + +# pardon my french +parse_json() { + # Tokenize the JSON using grep + grep -oE '"([^"\\]|\\.)*"|true|false|null|[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?|[{}[\]:,]' | \ + awk ' + BEGIN { + depth=0; + key="" + } + { + token = $0 + if (token == "{") { + depth++ + is_key[depth] = 1 + array_idx[depth] = "" + } else if (token == "}") { + delete path[depth] + delete array_idx[depth] + depth-- + } else if (token == "[") { + depth++ + is_key[depth] = 0 + array_idx[depth] = 0 + } else if (token == "]") { + delete array_idx[depth] + delete path[depth] + depth-- + } else if (token == ":") { + is_key[depth] = 0 + } else if (token == ",") { + if (array_idx[depth] != "") { + array_idx[depth]++ + } else { + is_key[depth] = 1 + } + } else { + if (is_key[depth] == 1) { + # Remove quotes from the key + gsub(/^"|"$/, "", token) + path[depth] = token + } else { + # It is a value + p = "" + for (i=1; i<=depth; i++) { + if (array_idx[i] != "") { + p = p "[" array_idx[i] "]" + } else if (path[i] != "") { + p = p "." path[i] + } + } + # Remove leading dot + sub(/^\./, "", p) + print p "=" token + } + } + } + ' +}