From c8b8b858bbba1e5e978fa2164eacf86fb28bd319 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sun, 13 Mar 2016 21:58:22 +0100 Subject: [PATCH] lldpcli: fix output with json-c to be the same as with jansson --- NEWS | 2 ++ src/client/jsonc_writer.c | 60 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c74174d1..ff85c936 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ lldpd (0.9.2) + Ability to add/remove/replace custom TLV from lldpcli. + LLDP-MED capabilities are displayed differently in lldpcli. + Limit the maximum depth (5) when trying to apply a VLAN. + + Change JSON output format when using json-c to match Jansson + output. * Fix: + LLDP-MED POE TLV are now displayed in lldpcli. + Ignore lower link when it is in another namespace. diff --git a/src/client/jsonc_writer.c b/src/client/jsonc_writer.c index a66cc0fb..88653830 100644 --- a/src/client/jsonc_writer.c +++ b/src/client/jsonc_writer.c @@ -101,6 +101,62 @@ jsonc_end(struct writer *w) free(current); } +/* When an array has only one member, just remove the array. When an object has + * `value` as the only key, remove the object. Moreover, for an object, move the + * `name` key outside (inside a new object). This is a recursive function. We + * think the depth will be limited. */ +static json_object* +jsonc_cleanup(json_object *el) +{ + json_object *new; + if (el == NULL) return NULL; + if (json_object_get_type(el) == json_type_array) { + size_t len = json_object_array_length(el); + if (len == 1) { + new = json_object_array_get_idx(el, 0); + return jsonc_cleanup(new); + } + new = json_object_new_array(); + for (size_t i = 0; i < len; i++) { + json_object_array_add(new, + jsonc_cleanup(json_object_array_get_idx(el, i))); + } + return new; + } + if (json_object_get_type(el) == json_type_object) { + if (json_object_object_length(el) == 1 && + json_object_object_get_ex(el, "value", &new)) { + json_object_get(new); + return new; /* This is a string or a boolean, no need to + * cleanup */ + } + + json_object *name = NULL; + new = json_object_new_object(); + json_object_object_foreach(el, key, value) { + value = jsonc_cleanup(value); + if (strcmp(key, "name") || + json_object_get_type(value) != json_type_string) { + json_object_object_add(new, key, value); + } else { + name = value; + } + } + if (name) { + /* Embed the current object into a new one with the name + * as key. */ + json_object *replacement = json_object_new_object(); + json_object_object_add(replacement, + json_object_get_string(name), new); + json_object_put(name); + return replacement; + } + return new; + } + json_object_get(el); + return el; +} + static void jsonc_finish(struct writer *w) { @@ -112,10 +168,12 @@ jsonc_finish(struct writer *w) /* memory will leak... */ } else { struct json_element *first = TAILQ_FIRST(&p->els); + json_object *export = jsonc_cleanup(first->el); int json_flags = (JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED); - const char *s = json_object_to_json_string_ext(first->el, json_flags); + const char *s = json_object_to_json_string_ext(export, json_flags); fprintf(p->fh, "%s", s?s:"{}"); json_object_put(first->el); + json_object_put(export); TAILQ_REMOVE(&p->els, first, next); free(first); } -- 2.39.5