summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorAdrian Vovk <adrianvovk@gmail.com>2024-07-03 23:57:42 +0200
committerAdrian Vovk <adrianvovk@gmail.com>2024-07-17 20:15:43 +0200
commitc4cb49eb342bb347fb974eb55236d2eb3e565086 (patch)
tree63280961c328ad348c129f8d516b4c66c7a3ba82 /src/shared
parenttable: Add TABLE_SET_JSON_FIELD_NAME (diff)
downloadsystemd-c4cb49eb342bb347fb974eb55236d2eb3e565086.tar.xz
systemd-c4cb49eb342bb347fb974eb55236d2eb3e565086.zip
table: Improve mangling of JSON field names
First, when displaying JSON we convert dashes into underscores. We want to avoid using dashes in JSON field names in new code, because some JSON parsers don't support dashes very well. Second, we make the first character of every word lower-case. This better matches our JSON field name style, and makes the automatic JSON name mangling a lot more useful for vertical tables, where fields are given a display name. For example, "Foo Bar" would be converted into "foo_bar" instead of "Foo_Bar", which much better matches our style. We don't make the whole string lowercase to support cases like: "fooBar" should stay as "fooBar". Some situations don't behave quite perfectly, such as "Foo BarBaz" gets converted into "foo_barBaz", or all-caps headings get mangled incorrectly. In these situations, the JSON field should be overridden manually. In most cases, or at least more cases than before, this heuristic does good enough.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/format-table.c35
-rw-r--r--src/shared/format-table.h1
2 files changed, 29 insertions, 7 deletions
diff --git a/src/shared/format-table.c b/src/shared/format-table.c
index e538d96414..ee641d1144 100644
--- a/src/shared/format-table.c
+++ b/src/shared/format-table.c
@@ -2895,18 +2895,39 @@ static int table_data_to_json(TableData *d, sd_json_variant **ret) {
}
}
-static char* string_to_json_field_name(const char *f) {
+char* table_mangle_to_json_field_name(const char *str) {
/* Tries to make a string more suitable as JSON field name. There are no strict rules defined what a
- * field name can be hence this is a bit vague and black magic. Right now we only convert spaces to
- * underscores and leave everything as is. */
+ * field name can be hence this is a bit vague and black magic. Here's what we do:
+ * - Convert spaces to underscores
+ * - Convert dashes to underscores (some JSON parsers don't like dealing with dashes)
+ * - Convert most other symbols to underscores (for similar reasons)
+ * - Make the first letter of each word lowercase (unless it looks like the whole word is uppercase)
+ */
- char *c = strdup(f);
+ bool new_word = true;
+ char *c;
+
+ assert(str);
+
+ c = strdup(str);
if (!c)
return NULL;
- for (char *x = c; *x; x++)
- if (isspace(*x))
+ for (char *x = c; *x; x++) {
+ if (!strchr(ALPHANUMERICAL, *x)) {
*x = '_';
+ new_word = true;
+ continue;
+ }
+
+ if (new_word) {
+ if (ascii_tolower(*(x + 1)) == *(x + 1)) /* Heuristic: if next char is upper-case
+ * then we assume the whole word is all-caps
+ * and avoid lowercasing it. */
+ *x = ascii_tolower(*x);
+ new_word = false;
+ }
+ }
return c;
}
@@ -2927,7 +2948,7 @@ static int table_make_json_field_name(Table *t, TableData *d, char **ret) {
return -ENOMEM;
}
- mangled = string_to_json_field_name(n);
+ mangled = table_mangle_to_json_field_name(n);
if (!mangled)
return -ENOMEM;
diff --git a/src/shared/format-table.h b/src/shared/format-table.h
index 15c0547b94..bb2eb70759 100644
--- a/src/shared/format-table.h
+++ b/src/shared/format-table.h
@@ -166,6 +166,7 @@ int table_print_json(Table *t, FILE *f, sd_json_format_flags_t json_flags);
int table_print_with_pager(Table *t, sd_json_format_flags_t json_format_flags, PagerFlags pager_flags, bool show_header);
+char* table_mangle_to_json_field_name(const char *str);
int table_set_json_field_name(Table *t, size_t idx, const char *name);
#define table_log_add_error(r) \