shithub: json2awk

Download patch

ref: 45c9730c403606806969a273b8032dd305cc83df
author: akw <akw@shithub>
date: Thu Mar 26 22:22:13 EDT 2026

initial import

--- /dev/null
+++ b/jawk
@@ -1,0 +1,8 @@
+#!/bin/rc
+jdefs = `''{json2awk}
+awk -f <{cat <<‽}
+BEGIN{
+	$jdefs
+	$*
+}
+‽
--- /dev/null
+++ b/json2awk.c
@@ -1,0 +1,151 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <json.h>
+
+typedef struct Level Level;
+struct Level {
+	int	noquote;
+	char	*name;
+	Level	*next;
+	Level	*prev;
+};
+
+Level *head = nil;
+Level *tail = nil;
+
+void
+lappend(int q, char *s)
+{
+	Level *new;
+
+	if((new = mallocz(sizeof(Level), 1)) == nil)
+		sysfatal("mallocz: %r");
+	new->noquote = !q;
+	new->name = s;
+	if(!head)
+		head = new;
+	if(tail)
+		tail->next = new;
+	new->prev = tail;
+	tail = new;
+}
+
+void
+lremove(void)
+{
+	void *v;
+
+	v = tail;
+	tail = tail->prev;
+	free(v);
+	if(tail == nil)
+		head = nil;
+	else
+		tail->next = nil;
+}
+
+#pragma	varargck	type	"L"	Level*
+int
+Lfmt(Fmt *f)
+{
+	Level *l;
+
+	l = va_arg(f->args, Level*);
+	while(l != nil){
+		if(l->noquote){
+			if(fmtprint(f, "%s", l->name) < 0)
+				return -1;
+		}else
+			if(fmtprint(f, "\"%s\"", l->name) < 0)
+				return -1;
+		
+		if(l->next != nil && fmtprint(f, ", ") < 0)
+				return -1;
+		l = l->next;
+	}
+	return 0;
+}
+
+void
+json2awk(JSON *j)
+{
+	JSONEl *e;
+	char *s;
+	int i;
+
+	switch(j->t){
+	case JSONArray:
+		e = j->first;
+		for(i = 0; e; i++){
+			s = smprint("%d", i);
+			lappend(0, s);
+			json2awk(e->val);
+			lremove();
+			e = e->next;
+			free(s);
+		}
+		break;
+	case JSONObject:
+		e = j->first;
+		do{
+			lappend(1, e->name);
+			json2awk(e->val);
+			lremove();
+		}while(e = e->next);
+		break;
+	case JSONBool:
+		print("json[%L] = %d;\n", head, (int)j->n);
+		break;
+	case JSONNumber:
+		print("json[%L] = %g;\n", head, j->n);
+		break;
+	case JSONString:
+		print("json[%L] = \"%s\";\n", head, j->s);
+		break;
+	case JSONNull:
+		break;
+	}
+}
+
+void
+main(int argc, char **argv)
+{
+	Level *l, *ln;
+	Biobuf *b;
+	JSON *J;
+	char *j;
+	int fd;
+
+	switch(argc){
+	case 1:
+		fd = 0;
+		break;
+	case 2:
+		fd = open(argv[1], OREAD);
+		break;
+	default:
+		fprint(2, "usage: json2awk [file]");
+		exits("usage");
+	}
+
+	/* read it all into j */
+	fmtinstall('L', Lfmt);
+	b = Bfdopen(fd, OREAD);
+	j = Brdstr(b, '\0', '\0');
+	if((J = jsonparse(j)) == nil)
+		sysfatal("jsonparse: %r");
+
+	json2awk(J);
+
+	jsonfree(J);
+	free(j);
+	free(b);
+	for(l = head; l != nil; l = ln){
+		ln = l->next;
+		free(l);
+	}
+
+	exits(0);
+}
+
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+
+TARG=json2awk
+BIN=/$objtype/bin
+OFILES=json2awk.$O
+HFILES=
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/weather.rc
@@ -1,0 +1,49 @@
+#!/bin/rc
+
+fn formparams {
+	urlp = $1'?'$2
+	shift 2
+	while(! ~ $#* 0){
+		urlp = $urlp'&'$1
+		shift
+	}
+	echo $urlp
+}
+
+fn pull {
+	purl = $1
+	shift
+	hget $purl | jawk $*
+}
+
+geourl = 'https://geocoding.geo.census.gov/geocoder/locations/address'
+street = '0000+REDACTED+AVE'
+zip = 99999
+
+geourl = `{formparams $geourl \
+	'street='$street \
+	'zip='$zip \
+	'format=json' \
+	'benchmark=Public_AR_Current'
+}
+
+# get our coordinates
+xy = `{pull $geourl '
+	print json["result", "addressMatches", 0, "coordinates", "x"]
+	print json["result", "addressMatches", 0, "coordinates", "y"]
+'}
+
+# get the forecast url for our location
+url = https://api.weather.gov/points/$xy(2)^,$xy(1)
+forecasturl = `{pull $url 'print json["properties", "forecast"]'}
+
+# print the forecast
+pull $forecasturl '
+	for(i = 0;; i++){
+		when = json["properties", "periods", i, "name"]
+		if(when == "")
+			break;
+		print when
+		print "\t" json["properties", "periods", i, "detailedForecast"]
+	}
+'
--