ref: a53ae2782a6e8b1996c1d5dea4190eb11d06d056
parent: f6e8b115d49e8aec463e3a495d53ee11031a4db6
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Dec 22 13:12:56 EST 2015
libjson: added printing support (thanks spew)
--- a/sys/include/json.h
+++ b/sys/include/json.h
@@ -4,6 +4,8 @@
typedef struct JSONEl JSONEl;
typedef struct JSON JSON;
+#pragma varargck type "J" JSON*
+
enum {
JSONNull,
JSONBool,
@@ -33,3 +35,5 @@
void jsonfree(JSON *);
JSON* jsonbyname(JSON *, char *);
char* jsonstr(JSON *);
+int JSONfmt(Fmt*);
+void JSONfmtinstall(void);
--- a/sys/man/2/json
+++ b/sys/man/2/json
@@ -40,10 +40,12 @@
};
};
-JSON* jsonparse(char *);
-void jsonfree(JSON *);
-JSON* jsonbyname(JSON *, char *);
-char* jsonstr(JSON *);
+JSON* jsonparse(char *s);
+void jsonfree(JSON *j);
+JSON* jsonbyname(JSON *j, char *s);
+char* jsonstr(JSON *j);
+int JSONfmt(Fmt *f)
+void JSONfmtinstall(void);
.EE
.SH DESCRIPTION
The
@@ -76,7 +78,7 @@
member set to the key of the association.
.P
A json object is parsed by calling
-.B jsonparse
+.I jsonparse
with a
.B UTF-8
string of the json encoded data. On success, a non-nil pointer to a
@@ -84,26 +86,41 @@
.B JSON
structure is returned.
To free the parsed objects,
-.B jsonfree
+.I jsonfree
has to be called.
.P
The
-.B jsonbyname
+.I jsonbyname
function returns the associated value of a dictionary item.
.P
The function
-.B jsonstr
+.I jsonstr
returns the string value of a json object or
.B nil
for any other object type.
+.P
+.I JSONfmt
+is a
+.IR print (2)
+formatting routine that prints a well-formatted JSON structure.
+It can be installed by hand but
+.I JSONfmtinstall
+installs it under the standard format character J. The header
+.B <json.h>
+contains a #pragma statement so the compiler can
+type-check uses of
+.B %J
+in
+.IR print (2)
+format strings.
.SH SOURCE
.B /sys/src/libjson
.SH DIAGNOSTICS
The functions
-.IB jsonparse ,
-.B jsonbyname
+.I jsonparse,
+.I jsonbyname
and
-.B jsonstr
+.I jsonstr
return
.B nil
on error and set an error string (see
--- a/sys/src/libjson/mkfile
+++ b/sys/src/libjson/mkfile
@@ -2,7 +2,8 @@
LIB=/$objtype/lib/libjson.a
OFILES=\
- json.$O
+ json.$O\
+ printjson.$O
HFILES=\
/sys/include/json.h
--- /dev/null
+++ b/sys/src/libjson/printjson.c
@@ -1,0 +1,93 @@
+#include <u.h>
+#include <libc.h>
+#include <json.h>
+
+static int printjson(Fmt*, JSON*, int);
+static int printarray(Fmt*, JSON*, int);
+static int printobject(Fmt*, JSON*, int);
+
+static int
+printarray(Fmt *f, JSON *j, int indent)
+{
+ JSONEl *jl;
+ int i, r;
+
+ if(j->first == nil){
+ return fmtprint(f, "[]");
+ }
+ r = fmtprint(f, "[\n");
+ for(jl = j->first; jl != nil; jl = jl->next){
+ for(i = 0; i < indent; i++)
+ r += fmtprint(f, "\t");
+ r += printjson(f, jl->val, indent);
+ r += fmtprint(f, "%s\n", jl->next != nil ? "," : "");
+ }
+ for(i = 0; i < indent-1; i++)
+ r += fmtprint(f, "\t");
+ r += fmtprint(f, "]");
+ return r;
+}
+
+static int
+printobject(Fmt *f, JSON *j, int indent)
+{
+ JSONEl *jl;
+ int i, r;
+
+ if(j->first == nil){
+ return fmtprint(f, "{}");
+ }
+ r = fmtprint(f, "{\n");
+ for(jl = j->first; jl != nil; jl = jl->next){
+ for(i = 0; i < indent; i++)
+ fmtprint(f, "\t");
+ r += fmtprint(f, "\"%s\": ", jl->name);
+ r += printjson(f, jl->val, indent);
+ r += fmtprint(f, "%s\n", jl->next != nil ? "," : "");
+ }
+ for(i = 0; i < indent-1; i++)
+ r += fmtprint(f, "\t");
+ r += fmtprint(f, "}");
+ return r;
+}
+
+static int
+printjson(Fmt *f, JSON *j, int indent)
+{
+ switch(j->t){
+ case JSONNull:
+ return fmtprint(f, "null");
+ break;
+ case JSONBool:
+ return fmtprint(f, "%s", j->n ? "true" : "false");
+ break;
+ case JSONNumber:
+ return fmtprint(f, "%f", j->n);
+ break;
+ case JSONString:
+ return fmtprint(f, "\"%s\"", j->s);
+ break;
+ case JSONArray:
+ return printarray(f, j, indent+1);
+ break;
+ case JSONObject:
+ return printobject(f, j, indent+1);
+ break;
+ }
+ return 0;
+}
+
+int
+JSONfmt(Fmt *f)
+{
+ JSON *j;
+
+ j = va_arg(f->args, JSON*);
+ return printjson(f, j, 0);
+}
+
+void
+JSONfmtinstall(void)
+{
+ fmtinstall('J', JSONfmt);
+}