diff --git a/sys/include/json.h b/sys/include/json.h index 9544a1e65..efe5cb56a 100644 --- 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 @@ JSON* jsonparse(char *); void jsonfree(JSON *); JSON* jsonbyname(JSON *, char *); char* jsonstr(JSON *); +int JSONfmt(Fmt*); +void JSONfmtinstall(void); diff --git a/sys/man/2/json b/sys/man/2/json index 44f7c3763..d24adace3 100644 --- a/sys/man/2/json +++ b/sys/man/2/json @@ -40,10 +40,12 @@ struct JSON }; }; -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 @@ Dictionary objects have the 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 @@ newly allocated .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 +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 diff --git a/sys/src/libjson/mkfile b/sys/src/libjson/mkfile index 3b61d9c89..016c2c021 100644 --- 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 diff --git a/sys/src/libjson/printjson.c b/sys/src/libjson/printjson.c new file mode 100644 index 000000000..aa6d52485 --- /dev/null +++ b/sys/src/libjson/printjson.c @@ -0,0 +1,93 @@ +#include +#include +#include + +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); +}