diff --git a/src/dir_export.c b/src/dir_export.c
index 3d32c1af12d77205c47fdea4c744ae9e0383f3ad..5ac6f2110cc4aae17428695f2aa5e3a8352a792a 100644
--- a/src/dir_export.c
+++ b/src/dir_export.c
@@ -31,7 +31,12 @@
 
 
 static FILE *stream;
-static int level; /* Current level of nesting */
+
+/* Stack of device IDs, also used to determine the  */
+struct stack {
+  uint64_t *list;
+  int size, top;
+} stack;
 
 
 static void output_string(const char *str) {
@@ -81,9 +86,10 @@ static void output_info(struct dir *d) {
     fputs(",\"dsize\":", stream);
     output_int((uint64_t)d->size);
   }
-  /* TODO: No need to include a dev is it's the same as the parent dir. */
-  fputs(",\"dev\":", stream);
-  output_int(d->dev);
+  if(d->dev != nstack_top(&stack, 0)) {
+    fputs(",\"dev\":", stream);
+    output_int(d->dev);
+  }
   fputs(",\"ino\":", stream);
   output_int(d->ino);
   if(d->flags & FF_HLNKC) /* TODO: Including the actual number of links would be nicer. */
@@ -93,9 +99,9 @@ static void output_info(struct dir *d) {
   if(!(d->flags & (FF_DIR|FF_FILE)))
     fputs(",\"notreg\":true", stream);
   if(d->flags & FF_EXL)
-    fputs(",\"excluded\":\"pattern", stream);
+    fputs(",\"excluded\":\"pattern\"", stream);
   else if(d->flags & FF_OTHFS)
-    fputs(",\"excluded\":\"othfs", stream);
+    fputs(",\"excluded\":\"othfs\"", stream);
   fputc('}', stream);
 }
 
@@ -107,7 +113,8 @@ static void output_info(struct dir *d) {
  * called with a stream that's in an error state. */
 static int item(struct dir *item) {
   if(!item) {
-    if(!--level) { /* closing of the root item */
+    nstack_pop(&stack);
+    if(!stack.top) { /* closing of the root item */
       fputs("]]", stream);
       return fclose(stream);
     } else /* closing of a regular directory item */
@@ -119,7 +126,7 @@ static int item(struct dir *item) {
 
   /* File header.
    * TODO: Add scan options? */
-  if(item->flags & FF_DIR && !level++)
+  if(!stack.top)
     fputs("[1,0,{\"progname\":\""PACKAGE"\",\"progver\":\""PACKAGE_VERSION"\"}", stream);
 
   fputs(",\n", stream);
@@ -127,11 +134,16 @@ static int item(struct dir *item) {
     fputc('[', stream);
 
   output_info(item);
+
+  if(item->flags & FF_DIR)
+    nstack_push(&stack, item->dev);
+
   return ferror(stream);
 }
 
 
 static int final(int fail) {
+  nstack_free(&stack);
   return fail ? 1 : 1; /* Silences -Wunused-parameter */
 }
 
@@ -142,7 +154,8 @@ int dir_export_init(const char *fn) {
   else if((stream = fopen(fn, "w")) == NULL)
     return 1;
 
-  level = 0;
+  nstack_init(&stack);
+
   pstate = ST_CALC;
   dir_output.item = item;
   dir_output.final = final;
diff --git a/src/util.h b/src/util.h
index ac6b46782b2513581540d194a2d45a1948066bc8..1213f98ad4e2647991cf74b14b12d1b38eef07e9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -84,5 +84,26 @@ struct dir *getroot(struct dir *);
 /* Adds a value to the size, asize and items fields of *d and its parents */
 void addparentstats(struct dir *, int64_t, int64_t, int);
 
+
+/* A simple stack implemented in macros */
+#define nstack_init(_s) do {\
+    (_s)->size = 10;\
+    (_s)->top = 0;\
+    (_s)->list = malloc(10*sizeof(*(_s)->list));\
+  } while(0)
+
+#define nstack_push(_s, _v) do {\
+    if((_s)->size <= (_s)->top) {\
+      (_s)->size *= 2;\
+      (_s)->list = realloc((_s)->list, (_s)->size*sizeof(*(_s)->list));\
+    }\
+    (_s)->list[(_s)->top++] = _v;\
+  } while(0)
+
+#define nstack_pop(_s) (_s)->top--
+#define nstack_top(_s, _d) ((_s)->top > 0 ? (_s)->list[(_s)->top-1] : (_d))
+#define nstack_free(_s) free((_s)->list)
+
+
 #endif