Skip to content

Commit 3fcffe1

Browse files
committedApr 28, 2012
Add a json_object_to_json_string_ext() function to allow the formatting of output to be selected.
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.
1 parent f931f61 commit 3fcffe1

File tree

5 files changed

+171
-51
lines changed

5 files changed

+171
-51
lines changed
 

‎json_object.c

+120-44
Original file line numberDiff line numberDiff line change
@@ -180,45 +180,88 @@ enum json_type json_object_get_type(struct json_object *jso)
180180
return jso->o_type;
181181
}
182182

183-
/* json_object_to_json_string */
183+
/* extended conversion to string */
184+
185+
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
186+
{
187+
if (!jso)
188+
return "null";
189+
190+
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
191+
return NULL;
192+
193+
printbuf_reset(jso->_pb);
194+
195+
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
196+
return NULL;
197+
198+
return jso->_pb->buf;
199+
}
200+
201+
/* backwards-compatible conversion to string */
184202

185203
const char* json_object_to_json_string(struct json_object *jso)
186204
{
187-
if(!jso) return "null";
188-
if(!jso->_pb) {
189-
if(!(jso->_pb = printbuf_new())) return NULL;
190-
} else {
191-
printbuf_reset(jso->_pb);
192-
}
193-
if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;
194-
return jso->_pb->buf;
205+
return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
195206
}
196207

208+
static void indent(struct printbuf *pb, int level, int flags)
209+
{
210+
if (flags & JSON_C_TO_STRING_PRETTY)
211+
{
212+
printbuf_memset(pb, -1, ' ', level * 2);
213+
}
214+
}
197215

198216
/* json_object_object */
199217

200218
static int json_object_object_to_json_string(struct json_object* jso,
201-
struct printbuf *pb)
202-
{
203-
int i=0;
204-
struct json_object_iter iter;
205-
sprintbuf(pb, "{");
206-
207-
/* CAW: scope operator to make ANSI correctness */
208-
/* CAW: switched to json_object_object_foreachC which uses an iterator struct */
209-
json_object_object_foreachC(jso, iter) {
210-
if(i) sprintbuf(pb, ",");
211-
sprintbuf(pb, " \"");
212-
json_escape_str(pb, iter.key, strlen(iter.key));
219+
struct printbuf *pb,
220+
int level,
221+
int flags)
222+
{
223+
int had_children = 0;
224+
struct json_object_iter iter;
225+
226+
sprintbuf(pb, "{" /*}*/);
227+
if (flags & JSON_C_TO_STRING_PRETTY)
228+
sprintbuf(pb, "\n");
229+
json_object_object_foreachC(jso, iter)
230+
{
231+
if (had_children)
232+
{
233+
sprintbuf(pb, ",");
234+
if (flags & JSON_C_TO_STRING_PRETTY)
235+
sprintbuf(pb, "\n");
236+
}
237+
had_children = 1;
238+
if (flags & JSON_C_TO_STRING_SPACED)
239+
sprintbuf(pb, " ");
240+
indent(pb, level+1, flags);
241+
sprintbuf(pb, "\"");
242+
json_escape_str(pb, iter.key, strlen(iter.key));
243+
if (flags & JSON_C_TO_STRING_SPACED)
213244
sprintbuf(pb, "\": ");
214-
if(iter.val == NULL) sprintbuf(pb, "null");
215-
else iter.val->_to_json_string(iter.val, pb);
216-
i++;
245+
else
246+
sprintbuf(pb, "\":");
247+
if(iter.val == NULL)
248+
sprintbuf(pb, "null");
249+
else
250+
iter.val->_to_json_string(iter.val, pb, level+1,flags);
217251
}
218-
219-
return sprintbuf(pb, " }");
252+
if (flags & JSON_C_TO_STRING_PRETTY)
253+
{
254+
if (had_children)
255+
sprintbuf(pb, "\n");
256+
indent(pb,level,flags);
257+
}
258+
if (flags & JSON_C_TO_STRING_SPACED)
259+
return sprintbuf(pb, /*{*/ " }");
260+
else
261+
return sprintbuf(pb, /*{*/ "}");
220262
}
221263

264+
222265
static void json_object_lh_entry_free(struct lh_entry *ent)
223266
{
224267
free(ent->k);
@@ -291,7 +334,9 @@ void json_object_object_del(struct json_object* jso, const char *key)
291334
/* json_object_boolean */
292335

293336
static int json_object_boolean_to_json_string(struct json_object* jso,
294-
struct printbuf *pb)
337+
struct printbuf *pb,
338+
int level,
339+
int flags)
295340
{
296341
if(jso->o.c_boolean) return sprintbuf(pb, "true");
297342
else return sprintbuf(pb, "false");
@@ -327,7 +372,9 @@ json_bool json_object_get_boolean(struct json_object *jso)
327372
/* json_object_int */
328373

329374
static int json_object_int_to_json_string(struct json_object* jso,
330-
struct printbuf *pb)
375+
struct printbuf *pb,
376+
int level,
377+
int flags)
331378
{
332379
return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
333380
}
@@ -412,7 +459,9 @@ int64_t json_object_get_int64(struct json_object *jso)
412459
/* json_object_double */
413460

414461
static int json_object_double_to_json_string(struct json_object* jso,
415-
struct printbuf *pb)
462+
struct printbuf *pb,
463+
int level,
464+
int flags)
416465
{
417466
return sprintbuf(pb, "%lf", jso->o.c_double);
418467
}
@@ -449,7 +498,9 @@ double json_object_get_double(struct json_object *jso)
449498
/* json_object_string */
450499

451500
static int json_object_string_to_json_string(struct json_object* jso,
452-
struct printbuf *pb)
501+
struct printbuf *pb,
502+
int level,
503+
int flags)
453504
{
454505
sprintbuf(pb, "\"");
455506
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) {
511562
/* json_object_array */
512563

513564
static int json_object_array_to_json_string(struct json_object* jso,
514-
struct printbuf *pb)
515-
{
516-
int i;
517-
sprintbuf(pb, "[");
518-
for(i=0; i < json_object_array_length(jso); i++) {
519-
struct json_object *val;
520-
if(i) { sprintbuf(pb, ", "); }
521-
else { sprintbuf(pb, " "); }
522-
523-
val = json_object_array_get_idx(jso, i);
524-
if(val == NULL) { sprintbuf(pb, "null"); }
525-
else { val->_to_json_string(val, pb); }
526-
}
527-
return sprintbuf(pb, " ]");
565+
struct printbuf *pb,
566+
int level,
567+
int flags)
568+
{
569+
int had_children = 0;
570+
int ii;
571+
sprintbuf(pb, "[");
572+
if (flags & JSON_C_TO_STRING_PRETTY)
573+
sprintbuf(pb, "\n");
574+
for(ii=0; ii < json_object_array_length(jso); ii++)
575+
{
576+
struct json_object *val;
577+
if (had_children)
578+
{
579+
sprintbuf(pb, ",");
580+
if (flags & JSON_C_TO_STRING_PRETTY)
581+
sprintbuf(pb, "\n");
582+
}
583+
had_children = 1;
584+
if (flags & JSON_C_TO_STRING_SPACED)
585+
sprintbuf(pb, " ");
586+
indent(pb, level + 1, flags);
587+
val = json_object_array_get_idx(jso, ii);
588+
if(val == NULL)
589+
sprintbuf(pb, "null");
590+
else
591+
val->_to_json_string(val, pb, level+1, flags);
592+
}
593+
if (flags & JSON_C_TO_STRING_PRETTY)
594+
{
595+
if (had_children)
596+
sprintbuf(pb, "\n");
597+
indent(pb,level,flags);
598+
}
599+
600+
if (flags & JSON_C_TO_STRING_SPACED)
601+
return sprintbuf(pb, " ]");
602+
else
603+
return sprintbuf(pb, "]");
528604
}
529605

530606
static void json_object_array_entry_free(void *data)

‎json_object.h

+32-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,28 @@ extern "C" {
2121

2222
#define JSON_OBJECT_DEF_HASH_ENTRIES 16
2323

24+
/**
25+
* A flag for the json_object_to_json_string_ext() and
26+
* json_object_to_file_ext() functions which causes the output
27+
* to have no extra whitespace or formatting applied.
28+
*/
29+
#define JSON_C_TO_STRING_PLAIN 0
30+
/**
31+
* A flag for the json_object_to_json_string_ext() and
32+
* json_object_to_file_ext() functions which causes the output to have
33+
* minimal whitespace inserted to make things slightly more readable.
34+
*/
35+
#define JSON_C_TO_STRING_SPACED (1<<0)
36+
/**
37+
* A flag for the json_object_to_json_string_ext() and
38+
* json_object_to_file_ext() functions which causes
39+
* the output to be formatted.
40+
*
41+
* See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
42+
* for an example of the format.
43+
*/
44+
#define JSON_C_TO_STRING_PRETTY (1<<1)
45+
2446
#undef FALSE
2547
#define FALSE ((json_bool)0)
2648

@@ -112,12 +134,21 @@ extern int json_object_is_type(struct json_object *obj, enum json_type type);
112134
extern enum json_type json_object_get_type(struct json_object *obj);
113135

114136

115-
/** Stringify object to json format
137+
/** Stringify object to json format.
138+
* Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
116139
* @param obj the json_object instance
117140
* @returns a string in JSON format
118141
*/
119142
extern const char* json_object_to_json_string(struct json_object *obj);
120143

144+
/** Stringify object to json format
145+
* @param obj the json_object instance
146+
* @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
147+
* @returns a string in JSON format
148+
*/
149+
extern const char* json_object_to_json_string_ext(struct json_object *obj, int
150+
flags);
151+
121152

122153
/* object type methods */
123154

‎json_object_private.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ extern "C" {
1818

1919
typedef void (json_object_delete_fn)(struct json_object *o);
2020
typedef int (json_object_to_json_string_fn)(struct json_object *o,
21-
struct printbuf *pb);
21+
struct printbuf *pb,
22+
int level,
23+
int flags);
2224

2325
struct json_object
2426
{

‎json_util.c

+14-5
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ struct json_object* json_object_from_file(const char *filename)
6565
if((fd = open(filename, O_RDONLY)) < 0) {
6666
MC_ERROR("json_object_from_file: error reading file %s: %s\n",
6767
filename, strerror(errno));
68-
return (struct json_object*)error_ptr(-1);
68+
return NULL; // XAX this is an API change!
6969
}
7070
if(!(pb = printbuf_new())) {
7171
close(fd);
7272
MC_ERROR("json_object_from_file: printbuf_new failed\n");
73-
return (struct json_object*)error_ptr(-1);
73+
return NULL;
7474
}
7575
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
7676
printbuf_memappend(pb, buf, ret);
@@ -80,14 +80,16 @@ struct json_object* json_object_from_file(const char *filename)
8080
MC_ABORT("json_object_from_file: error reading file %s: %s\n",
8181
filename, strerror(errno));
8282
printbuf_free(pb);
83-
return (struct json_object*)error_ptr(-1);
83+
return NULL;
8484
}
8585
obj = json_tokener_parse(pb->buf);
8686
printbuf_free(pb);
8787
return obj;
8888
}
8989

90-
int json_object_to_file(char *filename, struct json_object *obj)
90+
/* extended "format and write to file" function */
91+
92+
int json_object_to_file_ext(char *filename, struct json_object *obj, int flags)
9193
{
9294
const char *json_str;
9395
int fd, ret;
@@ -104,7 +106,7 @@ int json_object_to_file(char *filename, struct json_object *obj)
104106
return -1;
105107
}
106108

107-
if(!(json_str = json_object_to_json_string(obj))) {
109+
if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
108110
close(fd);
109111
return -1;
110112
}
@@ -127,6 +129,13 @@ int json_object_to_file(char *filename, struct json_object *obj)
127129
return 0;
128130
}
129131

132+
// backwards compatible "format and write to file" function
133+
134+
int json_object_to_file(char *filename, struct json_object *obj)
135+
{
136+
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
137+
}
138+
130139
int json_parse_int64(const char *buf, int64_t *retval)
131140
{
132141
int64_t num64;

‎json_util.h

+2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ extern "C" {
2323
/* utility functions */
2424
extern struct json_object* json_object_from_file(const char *filename);
2525
extern int json_object_to_file(char *filename, struct json_object *obj);
26+
extern int json_object_to_file_ext(char *filename, struct json_object *obj, int flags);
2627
extern int json_parse_int64(const char *buf, int64_t *retval);
2728

29+
2830
/**
2931
* Return a string describing the type of the object.
3032
* e.g. "int", or "object", etc...

0 commit comments

Comments
 (0)