]> granicus.if.org Git - json-c/commitdiff
Add a json_object_to_json_string_ext() function to allow the formatting of output...
authorEric Haszlakiewicz <erh+git@nimenees.com>
Sat, 28 Apr 2012 18:26:09 +0000 (13:26 -0500)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Sat, 28 Apr 2012 18:26:09 +0000 (13:26 -0500)
There are now three options: JSON_C_TO_STRING_SPACED, JSON_C_TO_STRING_PLAIN and JSON_C_TO_STRING_PRETTY.
This also add a json_object_to_file_ext() that takes the same flags.
Existing output of json_object_to_json_string() is unchanged, and uses JSON_C_TO_STRING_SPACED.
Thanks fo Grant Edwards for the initial patches.

json_object.c
json_object.h
json_object_private.h
json_util.c
json_util.h

index 84af414b4b3c3dbf4cdbe5d0ba7d85d8cd3a2cc2..825630fc3b51369ad8192fe8cff1a7181d3ca147 100644 (file)
@@ -180,45 +180,88 @@ enum json_type json_object_get_type(struct json_object *jso)
   return jso->o_type;
 }
 
-/* json_object_to_json_string */
+/* extended conversion to string */
+
+const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
+{
+       if (!jso)
+               return "null";
+
+       if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
+               return NULL;
+
+       printbuf_reset(jso->_pb);
+
+       if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
+               return NULL;
+
+       return jso->_pb->buf;
+}
+
+/* backwards-compatible conversion to string */
 
 const char* json_object_to_json_string(struct json_object *jso)
 {
-  if(!jso) return "null";
-  if(!jso->_pb) {
-    if(!(jso->_pb = printbuf_new())) return NULL;
-  } else {
-    printbuf_reset(jso->_pb);
-  }
-  if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;
-  return jso->_pb->buf;
+       return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
 }
 
+static void indent(struct printbuf *pb, int level, int flags)
+{
+       if (flags & JSON_C_TO_STRING_PRETTY)
+       {
+               printbuf_memset(pb, -1, ' ', level * 2);
+       }
+}
 
 /* json_object_object */
 
 static int json_object_object_to_json_string(struct json_object* jso,
-                                            struct printbuf *pb)
-{
-  int i=0;
-  struct json_object_iter iter;
-  sprintbuf(pb, "{");
-
-  /* CAW: scope operator to make ANSI correctness */
-  /* CAW: switched to json_object_object_foreachC which uses an iterator struct */
-       json_object_object_foreachC(jso, iter) {
-                       if(i) sprintbuf(pb, ",");
-                       sprintbuf(pb, " \"");
-                       json_escape_str(pb, iter.key, strlen(iter.key));
+                                            struct printbuf *pb,
+                                            int level,
+                                                int flags)
+{
+       int had_children = 0;
+       struct json_object_iter iter;
+
+       sprintbuf(pb, "{" /*}*/);
+       if (flags & JSON_C_TO_STRING_PRETTY)
+               sprintbuf(pb, "\n");
+       json_object_object_foreachC(jso, iter)
+       {
+               if (had_children)
+               {
+                       sprintbuf(pb, ",");
+                       if (flags & JSON_C_TO_STRING_PRETTY)
+                               sprintbuf(pb, "\n");
+               }
+               had_children = 1;
+               if (flags & JSON_C_TO_STRING_SPACED)
+                       sprintbuf(pb, " ");
+               indent(pb, level+1, flags);
+               sprintbuf(pb, "\"");
+               json_escape_str(pb, iter.key, strlen(iter.key));
+               if (flags & JSON_C_TO_STRING_SPACED)
                        sprintbuf(pb, "\": ");
-                       if(iter.val == NULL) sprintbuf(pb, "null");
-                       else iter.val->_to_json_string(iter.val, pb);
-                       i++;
+               else
+                       sprintbuf(pb, "\":");
+               if(iter.val == NULL)
+                       sprintbuf(pb, "null");
+               else
+                       iter.val->_to_json_string(iter.val, pb, level+1,flags);
        }
-
-  return sprintbuf(pb, " }");
+       if (flags & JSON_C_TO_STRING_PRETTY)
+       {
+               if (had_children)
+                       sprintbuf(pb, "\n");
+               indent(pb,level,flags);
+       }
+       if (flags & JSON_C_TO_STRING_SPACED)
+               return sprintbuf(pb, /*{*/ " }");
+       else
+               return sprintbuf(pb, /*{*/ "}");
 }
 
+
 static void json_object_lh_entry_free(struct lh_entry *ent)
 {
   free(ent->k);
@@ -291,7 +334,9 @@ void json_object_object_del(struct json_object* jso, const char *key)
 /* json_object_boolean */
 
 static int json_object_boolean_to_json_string(struct json_object* jso,
-                                             struct printbuf *pb)
+                                             struct printbuf *pb,
+                                             int level,
+                                                 int flags)
 {
   if(jso->o.c_boolean) return sprintbuf(pb, "true");
   else return sprintbuf(pb, "false");
@@ -327,7 +372,9 @@ json_bool json_object_get_boolean(struct json_object *jso)
 /* json_object_int */
 
 static int json_object_int_to_json_string(struct json_object* jso,
-                                         struct printbuf *pb)
+                                         struct printbuf *pb,
+                                         int level,
+                                         int flags)
 {
   return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
 }
@@ -412,7 +459,9 @@ int64_t json_object_get_int64(struct json_object *jso)
 /* json_object_double */
 
 static int json_object_double_to_json_string(struct json_object* jso,
-                                            struct printbuf *pb)
+                                            struct printbuf *pb,
+                                            int level,
+                                                int flags)
 {
   return sprintbuf(pb, "%lf", jso->o.c_double);
 }
@@ -449,7 +498,9 @@ double json_object_get_double(struct json_object *jso)
 /* json_object_string */
 
 static int json_object_string_to_json_string(struct json_object* jso,
-                                            struct printbuf *pb)
+                                            struct printbuf *pb,
+                                            int level,
+                                                int flags)
 {
   sprintbuf(pb, "\"");
   json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
@@ -511,20 +562,45 @@ int json_object_get_string_len(struct json_object *jso)  {
 /* json_object_array */
 
 static int json_object_array_to_json_string(struct json_object* jso,
-                                           struct printbuf *pb)
-{
-  int i;
-  sprintbuf(pb, "[");
-  for(i=0; i < json_object_array_length(jso); i++) {
-         struct json_object *val;
-         if(i) { sprintbuf(pb, ", "); }
-         else { sprintbuf(pb, " "); }
-
-      val = json_object_array_get_idx(jso, i);
-         if(val == NULL) { sprintbuf(pb, "null"); }
-         else { val->_to_json_string(val, pb); }
-  }
-  return sprintbuf(pb, " ]");
+                                            struct printbuf *pb,
+                                            int level,
+                                            int flags)
+{
+       int had_children = 0;
+       int ii;
+       sprintbuf(pb, "[");
+       if (flags & JSON_C_TO_STRING_PRETTY)
+               sprintbuf(pb, "\n");
+       for(ii=0; ii < json_object_array_length(jso); ii++)
+       {
+               struct json_object *val;
+               if (had_children)
+               {
+                       sprintbuf(pb, ",");
+                       if (flags & JSON_C_TO_STRING_PRETTY)
+                               sprintbuf(pb, "\n");
+               }
+               had_children = 1;
+               if (flags & JSON_C_TO_STRING_SPACED)
+                       sprintbuf(pb, " ");
+               indent(pb, level + 1, flags);
+               val = json_object_array_get_idx(jso, ii);
+               if(val == NULL)
+                       sprintbuf(pb, "null");
+               else
+                       val->_to_json_string(val, pb, level+1, flags);
+       }
+       if (flags & JSON_C_TO_STRING_PRETTY)
+       {
+               if (had_children)
+                       sprintbuf(pb, "\n");
+               indent(pb,level,flags);
+       }
+
+       if (flags & JSON_C_TO_STRING_SPACED)
+               return sprintbuf(pb, " ]");
+       else
+               return sprintbuf(pb, "]");
 }
 
 static void json_object_array_entry_free(void *data)
index f7ec9ea2bd2702ea09f22953478f1dea187db690..6520a9a7dbeb7fd9a805f195b42df1e47d017e80 100644 (file)
@@ -21,6 +21,28 @@ extern "C" {
 
 #define JSON_OBJECT_DEF_HASH_ENTRIES 16
 
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output
+ * to have no extra whitespace or formatting applied.
+ */
+#define JSON_C_TO_STRING_PLAIN      0
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output to have
+ * minimal whitespace inserted to make things slightly more readable.
+ */
+#define JSON_C_TO_STRING_SPACED     (1<<0)
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes
+ * the output to be formatted.
+ *
+ * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
+ * for an example of the format.
+ */
+#define JSON_C_TO_STRING_PRETTY     (1<<1)
+
 #undef FALSE
 #define FALSE ((json_bool)0)
 
@@ -112,12 +134,21 @@ extern int json_object_is_type(struct json_object *obj, enum json_type type);
 extern enum json_type json_object_get_type(struct json_object *obj);
 
 
-/** Stringify object to json format
+/** Stringify object to json format.
+ * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
  * @param obj the json_object instance
  * @returns a string in JSON format
  */
 extern const char* json_object_to_json_string(struct json_object *obj);
 
+/** Stringify object to json format
+ * @param obj the json_object instance
+ * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
+ * @returns a string in JSON format
+ */
+extern const char* json_object_to_json_string_ext(struct json_object *obj, int
+flags);
+
 
 /* object type methods */
 
index 112ce76f1df51bc24c796242a5b7faab81f5c47b..597332b980699f91a2d91a87f38562edc8de45de 100644 (file)
@@ -18,7 +18,9 @@ extern "C" {
 
 typedef void (json_object_delete_fn)(struct json_object *o);
 typedef int (json_object_to_json_string_fn)(struct json_object *o,
-                                           struct printbuf *pb);
+                                               struct printbuf *pb,
+                                               int level,
+                                               int flags);
 
 struct json_object
 {
index c6db882ee9ed83ef940eb0faa532d4f28b421807..e551d2dbb0605a20486ea8625c2b36ddaaa16e96 100644 (file)
@@ -65,12 +65,12 @@ struct json_object* json_object_from_file(const char *filename)
   if((fd = open(filename, O_RDONLY)) < 0) {
     MC_ERROR("json_object_from_file: error reading file %s: %s\n",
             filename, strerror(errno));
-    return (struct json_object*)error_ptr(-1);
+    return NULL; // XAX this is an API change!
   }
   if(!(pb = printbuf_new())) {
     close(fd);
     MC_ERROR("json_object_from_file: printbuf_new failed\n");
-    return (struct json_object*)error_ptr(-1);
+    return NULL;
   }
   while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
     printbuf_memappend(pb, buf, ret);
@@ -80,14 +80,16 @@ struct json_object* json_object_from_file(const char *filename)
     MC_ABORT("json_object_from_file: error reading file %s: %s\n",
             filename, strerror(errno));
     printbuf_free(pb);
-    return (struct json_object*)error_ptr(-1);
+    return NULL;
   }
   obj = json_tokener_parse(pb->buf);
   printbuf_free(pb);
   return obj;
 }
 
-int json_object_to_file(char *filename, struct json_object *obj)
+/* extended "format and write to file" function */
+
+int json_object_to_file_ext(char *filename, struct json_object *obj, int flags)
 {
   const char *json_str;
   int fd, ret;
@@ -104,7 +106,7 @@ int json_object_to_file(char *filename, struct json_object *obj)
     return -1;
   }
 
-  if(!(json_str = json_object_to_json_string(obj))) {
+  if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
     close(fd);
     return -1;
   }
@@ -127,6 +129,13 @@ int json_object_to_file(char *filename, struct json_object *obj)
   return 0;
 }
 
+// backwards compatible "format and write to file" function
+
+int json_object_to_file(char *filename, struct json_object *obj)
+{
+  return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
+}
+
 int json_parse_int64(const char *buf, int64_t *retval)
 {
        int64_t num64;
index a77305eca08e916a85a874967ccb89b8b7492dfe..277c3a745a1e4c904c963aa0627a3d2a18989a73 100644 (file)
@@ -23,8 +23,10 @@ extern "C" {
 /* utility functions */
 extern struct json_object* json_object_from_file(const char *filename);
 extern int json_object_to_file(char *filename, struct json_object *obj);
+extern int json_object_to_file_ext(char *filename, struct json_object *obj, int flags);
 extern int json_parse_int64(const char *buf, int64_t *retval);
 
+
 /**
  * Return a string describing the type of the object.
  * e.g. "int", or "object", etc...