From: Karel Zak Date: Fri, 8 Jan 2021 12:12:57 +0000 (+0100) Subject: libsmartcols: support arrays for JSON output X-Git-Tag: v2.37-rc1~195 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c7355dd63159427c959391c500fccecd0a18ba8;p=thirdparty%2Futil-linux.git libsmartcols: support arrays for JSON output 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 --- diff --git a/lib/jsonwrt.c b/lib/jsonwrt.c index 00e8b9d251..94b4a5dda8 100644 --- a/lib/jsonwrt.c +++ b/lib/jsonwrt.c @@ -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: diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index d4be9969a0..4c17eb1dc7 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -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 }; /* diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index 2293a43faa..918ec5c64d 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -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: