]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpcli: fix output with json-c to be the same as with jansson
authorVincent Bernat <vincent@bernat.im>
Sun, 13 Mar 2016 20:58:22 +0000 (21:58 +0100)
committerVincent Bernat <vincent@bernat.im>
Sun, 13 Mar 2016 20:58:22 +0000 (21:58 +0100)
NEWS
src/client/jsonc_writer.c

diff --git a/NEWS b/NEWS
index c74174d1cb18833d4800b208482185c296447127..ff85c936229e5bfd103eb4ec9680810ab1694f2b 100644 (file)
--- 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.
index a66cc0fbcdcb703a2765d3e9a50f89b504d59f2e..8865383008f054f27d7bad5cc75129be0fcef251 100644 (file)
@@ -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);
        }