]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: support arrays for JSON output
authorKarel Zak <kzak@redhat.com>
Fri, 8 Jan 2021 12:12:57 +0000 (13:12 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 8 Jan 2021 12:12:57 +0000 (13:12 +0100)
This patch add support to format multi-line cells (columns with
SCOLS_FL_WRAP) to arrays in JSON output.

For example mountpoints[] in lsblk output:

Normal output:
 $ lsblk -oNAME,FSTYPE,TYPE,MOUNTPOINTS /dev/sdc1
 NAME FSTYPE TYPE MOUNTPOINTS
 sdc1 btrfs  part /mnt/A
  /mnt/test
  /mnt/B

JSON output:
$ lsblk -J -oNAME,FSTYPE,TYPE,MOUNTPOINTS /dev/sdc1
{
   "blockdevices": [
      {
 "name": "sdc1",
 "fstype": "btrfs",
 "type": "part",
 "mountpoints": [
     "/mnt/A",
     "/mnt/test",
     "/mnt/B"
 ]
      }
   ]
}

Signed-off-by: Karel Zak <kzak@redhat.com>
lib/jsonwrt.c
libsmartcols/src/libsmartcols.h.in
libsmartcols/src/print.c

index 00e8b9d2512654b1d74b5d17567a7ffa3fbc6c60..94b4a5dda8d69e2f01c90cbe90f4db7cf577363c 100644 (file)
@@ -44,7 +44,7 @@ void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type)
                fmt->indent++;
                break;
        case UL_JSON_ARRAY:
-               fputs(name ? ": [\n" : "{\n", fmt->out);
+               fputs(name ? ": [\n" : "[\n", fmt->out);
                fmt->indent++;
                break;
        case UL_JSON_VALUE:
index d4be9969a0c96ac3b570e35b1c8ad9a8e1d4a2af..4c17eb1dc750308a16ebe5c9e19010176cb2b185 100644 (file)
@@ -93,7 +93,9 @@ enum {
 enum {
        SCOLS_JSON_STRING    = 0,       /* default */
        SCOLS_JSON_NUMBER    = 1,
-       SCOLS_JSON_BOOLEAN   = 2
+       SCOLS_JSON_BOOLEAN   = 2,
+       SCOLS_JSON_ARRAY_STRING = 3,        /* e.g. for multi-line (SCOLS_FL_WRAP) cells */
+       SCOLS_JSON_ARRAY_NUMBER = 4
 };
 
 /*
index 2293a43faa92293cb78f9dea0f325c26c57fbdc9..918ec5c64d31f21a29a0a34aa6f4b199ae855a7a 100644 (file)
@@ -435,6 +435,51 @@ err:
        return -errno;
 }
 
+static void print_json_data(struct libscols_table *tb,
+                           struct libscols_column *cl,
+                           const char *name,
+                           char *data,
+                           int is_last)
+{
+       switch (cl->json_type) {
+       case SCOLS_JSON_STRING:
+               /* name: "aaa" */
+               ul_jsonwrt_value_s(&tb->json, name, data, is_last);
+               break;
+       case SCOLS_JSON_NUMBER:
+               /* name: 123 */
+               ul_jsonwrt_value_raw(&tb->json, name, data, is_last);
+               break;
+       case SCOLS_JSON_BOOLEAN:
+               /* name: true|false */
+               ul_jsonwrt_value_boolean(&tb->json, name,
+                       !*data ? 0 :
+                       *data == '0' ? 0 :
+                       *data == 'N' || *data == 'n' ? 0 : 1,
+                       is_last);
+               break;
+       case SCOLS_JSON_ARRAY_STRING:
+       case SCOLS_JSON_ARRAY_NUMBER:
+               /* name: [ "aaa", "bbb", "ccc" ] */
+               ul_jsonwrt_array_open(&tb->json, name);
+
+               if (!scols_column_is_customwrap(cl))
+                       ul_jsonwrt_value_s(&tb->json, NULL, data, 1);
+               else do {
+                               char *next = cl->wrap_nextchunk(cl, data, cl->wrapfunc_data);
+
+                               if (cl->json_type == SCOLS_JSON_ARRAY_STRING)
+                                       ul_jsonwrt_value_s(&tb->json, NULL, data, next ? 0 : 1);
+                               else
+                                       ul_jsonwrt_value_raw(&tb->json, NULL, data, next ? 0 : 1);
+                               data = next;
+               } while (data);
+
+               ul_jsonwrt_array_close(&tb->json, is_last);
+               break;
+       }
+}
+
 static int print_data(struct libscols_table *tb,
                      struct libscols_column *cl,
                      struct libscols_line *ln, /* optional */
@@ -482,21 +527,7 @@ static int print_data(struct libscols_table *tb,
                return 0;
 
        case SCOLS_FMT_JSON:
-               switch (cl->json_type) {
-               case SCOLS_JSON_STRING:
-                       ul_jsonwrt_value_s(&tb->json, name, data, is_last);
-                       break;
-               case SCOLS_JSON_NUMBER:
-                       ul_jsonwrt_value_raw(&tb->json, name, data, is_last);
-                       break;
-               case SCOLS_JSON_BOOLEAN:
-                       ul_jsonwrt_value_boolean(&tb->json, name,
-                               !*data ? 0 :
-                               *data == '0' ? 0 :
-                               *data == 'N' || *data == 'n' ? 0 : 1,
-                               is_last);
-                       break;
-               }
+               print_json_data(tb, cl, name, data, is_last);
                return 0;
 
        case SCOLS_FMT_HUMAN: