mmcli: add json output support

Signed-off-by: Maxim Anisimov <maxim.anisimov.ua@gmail.com>
This commit is contained in:
Maxim Anisimov
2019-08-08 11:12:33 +03:00
committed by Aleksander Morgado
parent b0ec3030a3
commit d1ac5ca16b
3 changed files with 133 additions and 3 deletions

View File

@@ -1071,6 +1071,119 @@ dump_output_list_keyvalue (MmcF field)
}
}
/******************************************************************************/
/* Json-friendly output */
static gint
list_sort_by_keys (const OutputItem *item_a,
const OutputItem *item_b)
{
return g_strcmp0(field_infos[item_a->field].key, field_infos[item_b->field].key);
}
static void
dump_output_json (void)
{
GList *l;
MmcF current_field = MMC_F_UNKNOWN;
gchar **current_path = NULL;
guint cur_dlen = 0;
GRegex *escape_regex;
output_items = g_list_sort (output_items, (GCompareFunc) list_sort_by_keys);
escape_regex = g_regex_new("'", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
g_print("{");
for (l = output_items; l; l = g_list_next (l)) {
OutputItem *item_l = (OutputItem *)(l->data);
if (current_field != item_l->field) {
guint new_dlen;
guint iter = 0;
gchar **new_path;
new_path = g_strsplit(field_infos[item_l->field].key, ".", -1);
new_dlen = g_strv_length(new_path) - 1;
if (current_path) {
guint min_dlen = MIN (cur_dlen, new_dlen);
while(iter < min_dlen && g_strcmp0(current_path[iter], new_path[iter]) == 0)
iter++;
g_strfreev(current_path);
if (iter < min_dlen || new_dlen < cur_dlen)
for(min_dlen = iter; min_dlen < cur_dlen; min_dlen++)
g_print("}");
g_print(",");
}
while(iter < new_dlen)
g_print("\"%s\":{", new_path[iter++]);
cur_dlen = new_dlen;
current_path = new_path;
current_field = item_l->field;
} else {
g_print(",");
}
if (item_l->type == VALUE_TYPE_SINGLE) {
OutputItemSingle *single = (OutputItemSingle *) item_l;
gchar *escaped = NULL;
if (single->value)
escaped = g_regex_replace_literal(escape_regex, single->value, -1, 0, "\"", 0, NULL);
g_print ("\"%s\":\"%s\"", current_path[cur_dlen], escaped ? escaped : "--");
g_free (escaped);
} else if (item_l->type == VALUE_TYPE_MULTIPLE) {
OutputItemMultiple *multiple = (OutputItemMultiple *) item_l;
guint i, n = multiple->values ? g_strv_length (multiple->values) : 0;
g_print ("\"%s\":[", current_path[cur_dlen]);
for(i = 0; i < n; i++) {
gchar *escaped = g_regex_replace_literal(escape_regex, multiple->values[i], -1, 0, "\"", 0, NULL);
g_print("\"%s\"", escaped);
if (i < n - 1)
g_print(",");
g_free (escaped);
}
g_print("]");
} else {
g_assert_not_reached ();
}
}
while(cur_dlen--)
g_print("}");
g_print("}\n");
if (current_path)
g_strfreev(current_path);
g_regex_unref(escape_regex);
}
static void
dump_output_list_json (MmcF field)
{
GList *l;
g_assert (field != MMC_F_UNKNOWN);
g_print("{\"%s\":[", field_infos[field].key);
for (l = output_items; l; l = g_list_next (l)) {
OutputItem *item_l;
OutputItemListitem *listitem;
item_l = (OutputItem *)(l->data);
g_assert (item_l->type == VALUE_TYPE_LISTITEM);
listitem = (OutputItemListitem *)item_l;
g_assert (listitem->value);
/* All items must be of same type */
g_assert_cmpint (item_l->field, ==, field);
g_print("\"%s\"", listitem->value);
if (g_list_next(l))
g_print(",");
}
g_print("]}\n");
}
/******************************************************************************/
/* Dump output */
@@ -1086,6 +1199,9 @@ mmcli_output_dump (void)
case MMC_OUTPUT_TYPE_KEYVALUE:
dump_output_keyvalue ();
break;
case MMC_OUTPUT_TYPE_JSON:
dump_output_json ();
break;
}
g_list_free_full (output_items, (GDestroyNotify) output_item_free);
@@ -1106,6 +1222,9 @@ mmcli_output_list_dump (MmcF field)
case MMC_OUTPUT_TYPE_KEYVALUE:
dump_output_list_keyvalue (field);
break;
case MMC_OUTPUT_TYPE_JSON:
dump_output_list_json (field);
break;
}
g_list_free_full (output_items, (GDestroyNotify) output_item_free);