--- /dev/null
+/* example2.c - second example in the programming guide
+ *
+ * This file is Copyright (c) 2014 by Eric S. Raymond
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "microjson.h"
+
+#define MAXCHANNELS 72
+
+static bool usedflags[MAXCHANNELS];
+static int PRN[MAXCHANNELS];
+static int elevation[MAXCHANNELS];
+static int azimuth[MAXCHANNELS];
+static int visible;
+
+const struct json_attr_t sat_attrs[] = {
+ {"PRN", t_integer, .addr.integer = PRN},
+ {"el", t_integer, .addr.integer = elevation},
+ {"az", t_integer, .addr.integer = azimuth},
+ {"used", t_boolean, .addr.boolean = usedflags},
+ {NULL},
+};
+
+const struct json_attr_t json_attrs_sky[] = {
+ {"class", t_check, .dflt.check = "SKY"},
+ {"satellites", t_array, .addr.array.element_type = t_object,
+ .addr.array.arr.objects.subtype=sat_attrs,
+ .addr.array.maxlen = MAXCHANNELS,
+ .addr.array.count = &visible},
+ {NULL},
+ };
+
+int main(int argc, char *argv[])
+{
+ int i, status = 0;
+
+ status = json_read_object(argv[1], json_attrs_sky, NULL);
+ printf("%d satellites:\n", visible);
+ for (i = 0; i < visible; i++)
+ printf("PRN = %d, elevation = %d, azimuth = %d\n",
+ PRN[i], elevation[i], azimuth[i]);
+
+ if (status != 0)
+ puts(json_error_string(status));
+}
+
+/* end */
--- /dev/null
+/* example2.c - first example in the programming guide
+ *
+ * This file is Copyright (c) 2014 by Eric S. Raymond
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+
+#include "microjson.h"
+
+#define MAXUSERDEVS 4
+
+struct devconfig_t {
+ char path[PATH_MAX];
+ double activated;
+};
+
+struct devlist_t {
+ int ndevices;
+ struct devconfig_t list[MAXUSERDEVS];
+};
+
+static struct devlist_t devicelist;
+
+static int json_devicelist_read(const char *buf)
+{
+ const struct json_attr_t json_attrs_subdevice[] = {
+ {"path", t_string, STRUCTOBJECT(struct devconfig_t, path),
+ .len = sizeof(devicelist.list[0].path)},
+ {"activated", t_time, STRUCTOBJECT(struct devconfig_t, activated)},
+ {"activated", t_real, STRUCTOBJECT(struct devconfig_t, activated)},
+ {NULL},
+ };
+ const struct json_attr_t json_attrs_devices[] = {
+ {"class", t_check,.dflt.check = "DEVICES"},
+ {"devices", t_array, STRUCTARRAY(devicelist.list,
+ json_attrs_subdevice,
+ &devicelist.ndevices)},
+ {NULL},
+ };
+ int status;
+
+ memset(&devicelist, '\0', sizeof(devicelist));
+ status = json_read_object(buf, json_attrs_devices, NULL);
+ if (status != 0) {
+ return status;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, status = 0;
+
+ status = json_devicelist_read(argv[1]);
+ printf("%d devices:\n", devicelist.ndevices);
+ for (i = 0; i < devicelist.ndevices; i++)
+ printf("%s @ %f\n",
+ devicelist.list[i].path, devicelist.list[i].activated);
+
+ if (status != 0)
+ puts(json_error_string(status));
+}
+
+/* end */
matched. When the parse succeeds, attribute values will be extracted
into static locations specified in the template structures.
+== How To Use This Document ==
+
+This is a fast tutorial for working programmers. It teaches by
+examples; if you read the code carefully it will tell you
+more than the accompanying test. Just read it in sequence, trying not
+to skip anything.
+
+All the examples are shipped in the microjson distribution. They are
+not synthetic toys, but stripped-down versions of working code from
+GPS. Copy them freely.
+
== An Example ==
Here is nearly the simplest possible example:
+.Example 1
---------------------------------------------------------------------
+/*
+ * Parse JSON shaped like '{"flag1":true,"flag2":false,"count":42}'
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
Another field of the structure specifies the array's element type,
which can be any simple type or t_object (meaning a JSON subobject).
-If the array has simple elements, two three additional things must be
+If the array has simple elements, three additional things must be
specified: the base address of the array's storage, the maximum number
of elements it can have, and an integer address where the parser will
place a count of elements filled in.
The array element type may be +t_object+, as in the +satellites+ field
in this example:
+.Example 2
------------------------------------------------------------------------
-bool usedflags[MAXCHANNELS];
-int PRN[MAXCHANNELS];
-int elevation[MAXCHANNELS];
-int azimuth[MAXCHANNELS];
-int visible;
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "microjson.h"
+
+#define MAXCHANNELS 72
+
+static bool usedflags[MAXCHANNELS];
+static int PRN[MAXCHANNELS];
+static int elevation[MAXCHANNELS];
+static int azimuth[MAXCHANNELS];
+static int visible;
const struct json_attr_t sat_attrs[] = {
{"PRN", t_integer, .addr.integer = PRN},
.addr.array.count = &visible},
{NULL},
};
+
+int main(int argc, char *argv[])
+{
+ int i, status = 0;
+
+ status = json_read_object(argv[1], json_attrs_sky, NULL);
+ printf("%d satellites:\n", visible);
+ for (i = 0; i < visible; i++)
+ printf("PRN = %d, elevation = %d, azimuth = %d\n",
+ PRN[i], elevation[i], azimuth[i]);
+
+ if (status != 0)
+ puts(json_error_string(status));
+}
------------------------------------------------------------------------
-An example of the shape of JSON this would unpack is:
+Here's an example invocation (string literal folded for readability):
--------------------------------------------------------
-{"class":"SKY","satellites":[
- {"PRN":10,"el":45,"az":196,"used":true},
- {"PRN":29,"el":67,"az":310,"used":true},
- {"PRN":28,"el":59,"az":108,"used":true},
- {"PRN":26,"el":51,"az":304,"used":true},
- {"PRN":8, "el":44,"az":58, "used":true},
- {"PRN":27,"el":16,"az":66, "used":true},
- {"PRN":21,"el":10,"az":301,"used":false}
-]}
+$ example2 '{"class":"SKY","satellites":
+ [{"PRN":10,"el":45,"az":196,"used":true},
+ {"PRN":29,"el":67,"az":310,"used":true}]}'
+2 satellites:
+PRN = 10, elevation = 45, azimuth = 196
+PRN = 29, elevation = 67, azimuth = 310
--------------------------------------------------------
In this case, the parser needs to be told where to find a template
==== Structure arrays ====
-t_structobject: this also parses
+There's a different way to parse arrays that can unpack an
+array of JSON objects directly into an array of C structs.
+.Example 3:
+--------------------------------------------------------
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+
+#include "microjson.h"
+#define MAXUSERDEVS 4
+
+struct devconfig_t {
+ char path[PATH_MAX];
+ double activated;
+};
+
+struct devlist_t {
+ int ndevices;
+ struct devconfig_t list[MAXUSERDEVS];
+};
+
+static struct devlist_t devicelist;
+
+static int json_devicelist_read(const char *buf)
+{
+ const struct json_attr_t json_attrs_subdevice[] = {
+ {"path", t_string, STRUCTOBJECT(struct devconfig_t, path),
+ .len = sizeof(devicelist.list[0].path)},
+ {"activated", t_time, STRUCTOBJECT(struct devconfig_t, activated)},
+ {"activated", t_real, STRUCTOBJECT(struct devconfig_t, activated)},
+ {NULL},
+ };
+ const struct json_attr_t json_attrs_devices[] = {
+ {"class", t_check,.dflt.check = "DEVICES"},
+ {"devices", t_array, STRUCTARRAY(devicelist.list,
+ json_attrs_subdevice,
+ &devicelist.ndevices)},
+ {NULL},
+ };
+ int status;
+
+ memset(&devicelist, '\0', sizeof(devicelist));
+ status = json_read_object(buf, json_attrs_devices, NULL);
+ if (status != 0) {
+ return status;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, status = 0;
+
+ status = json_devicelist_read(argv[1]);
+ printf("%d devices:\n", devicelist.ndevices);
+ for (i = 0; i < devicelist.ndevices; i++)
+ printf("%s @ %f\n",
+ devicelist.list[i].path, devicelist.list[i].activated);
+
+ if (status != 0)
+ puts(json_error_string(status));
+}
+--------------------------------------------------------
+
+Here is an example:
+
+--------------------------------------------------------
+$ example3 '{"devices":[{"path":"/dev/ttyUSB0",
+ "activated":"2014-09-23T10:32:20"}]}'
+1 devices:
+/dev/ttyUSB0 @ 1411468340.000000
+--------------------------------------------------------
+In this case, the STRUCTARRAY and STRUCTOBJECT macros are clues to
+what is going on. STRUCTOBJECT is a thin wrapper around offsetof();
+STRUCTARRAY sets up the parser to walk through the array of
+structures, filling each element as it goes.