diff options
author | Adrian Vovk <adrianvovk@gmail.com> | 2024-07-03 23:57:42 +0200 |
---|---|---|
committer | Adrian Vovk <adrianvovk@gmail.com> | 2024-07-17 20:15:43 +0200 |
commit | c4cb49eb342bb347fb974eb55236d2eb3e565086 (patch) | |
tree | 63280961c328ad348c129f8d516b4c66c7a3ba82 /src/shared | |
parent | table: Add TABLE_SET_JSON_FIELD_NAME (diff) | |
download | systemd-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.c | 35 | ||||
-rw-r--r-- | src/shared/format-table.h | 1 |
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) \ |