size_t *sort_map; /* The columns to order rows by, in order of preference. */
size_t n_sort_map;
+ char **json_fields;
+ size_t n_json_fields;
+
bool *reverse_map;
char *empty_string;
free(t->reverse_map);
free(t->empty_string);
+ for (size_t i = 0; i < t->n_json_fields; i++)
+ free(t->json_fields[i]);
+
+ free(t->json_fields);
+
return mfree(t);
}
return c;
}
+static const char *table_get_json_field_name(Table *t, size_t column) {
+ assert(t);
+
+ return column < t->n_json_fields ? t->json_fields[column] : NULL;
+}
+
int table_to_json(Table *t, JsonVariant **ret) {
JsonVariant **rows = NULL, **elements = NULL;
_cleanup_free_ size_t *sorted = NULL;
for (size_t j = 0; j < display_columns; j++) {
_cleanup_free_ char *mangled = NULL;
- const char *formatted;
- TableData *d;
+ const char *n;
+ size_t c;
- assert_se(d = t->data[t->display_map ? t->display_map[j] : j]);
+ c = t->display_map ? t->display_map[j] : j;
- /* Field names must be strings, hence format whatever we got here as a string first */
- formatted = table_data_format(t, d, true, SIZE_MAX, NULL);
- if (!formatted) {
- r = -ENOMEM;
- goto finish;
- }
+ /* Use explicitly set JSON field name, if we have one. Otherwise mangle the column field value. */
+ n = table_get_json_field_name(t, c);
+ if (!n) {
+ const char *formatted;
+ TableData *d;
- /* Arbitrary strings suck as field names, try to mangle them into something more suitable hence */
- mangled = string_to_json_field_name(formatted);
- if (!mangled) {
- r = -ENOMEM;
- goto finish;
+ assert_se(d = t->data[c]);
+
+ /* Field names must be strings, hence format whatever we got here as a string first */
+ formatted = table_data_format(t, d, true, SIZE_MAX, NULL);
+ if (!formatted) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ /* Arbitrary strings suck as field names, try to mangle them into something more suitable hence */
+ mangled = string_to_json_field_name(formatted);
+ if (!mangled) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ n = mangled;
}
- r = json_variant_new_string(elements + j*2, mangled);
+ r = json_variant_new_string(elements + j*2, n);
if (r < 0)
goto finish;
}
return 0;
}
+
+int table_set_json_field_name(Table *t, size_t column, const char *name) {
+ int r;
+
+ assert(t);
+
+ if (name) {
+ size_t m;
+
+ m = MAX(column + 1, t->n_json_fields);
+ if (!GREEDY_REALLOC0(t->json_fields, m))
+ return -ENOMEM;
+
+ r = free_and_strdup(t->json_fields + column, name);
+ if (r < 0)
+ return r;
+
+ t->n_json_fields = m;
+ return r;
+ } else {
+ if (column >= t->n_json_fields)
+ return 0;
+
+ t->json_fields[column] = mfree(t->json_fields[column]);
+ return 1;
+ }
+}
int table_print_with_pager(Table *t, JsonFormatFlags json_format_flags, PagerFlags pager_flags, bool show_header);
+int table_set_json_field_name(Table *t, size_t column, const char *name);
+
#define table_log_add_error(r) \
log_error_errno(r, "Failed to add cell(s) to table: %m")
formatted = mfree(formatted);
}
+static void test_json(void) {
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
+ _cleanup_(table_unrefp) Table *t = NULL;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(t = table_new("foo bar", "quux", "piep miau"));
+ assert_se(table_set_json_field_name(t, 2, "zzz") >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "v1",
+ TABLE_UINT64, UINT64_C(4711),
+ TABLE_BOOLEAN, true) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRV, STRV_MAKE("a", "b", "c"),
+ TABLE_EMPTY,
+ TABLE_MODE, 0755) >= 0);
+
+ assert_se(table_to_json(t, &v) >= 0);
+
+ assert_se(json_build(&w,
+ JSON_BUILD_ARRAY(
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR("foo_bar", JSON_BUILD_STRING("v1")),
+ JSON_BUILD_PAIR("quux", JSON_BUILD_UNSIGNED(4711)),
+ JSON_BUILD_PAIR("zzz", JSON_BUILD_BOOLEAN(true))),
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR("foo_bar", JSON_BUILD_STRV(STRV_MAKE("a", "b", "c"))),
+ JSON_BUILD_PAIR("quux", JSON_BUILD_NULL),
+ JSON_BUILD_PAIR("zzz", JSON_BUILD_UNSIGNED(0755))))) >= 0);
+
+ assert_se(json_variant_equal(v, w));
+}
+
int main(int argc, char *argv[]) {
_cleanup_(table_unrefp) Table *t = NULL;
_cleanup_free_ char *formatted = NULL;
test_multiline();
test_strv();
test_strv_wrapped();
+ test_json();
return 0;
}