Browse Source

json: more sanity checks on JSON output.

We should never have an unnamed element, nor an named array field.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
6b740e78bd
  1. 76
      common/json.c

76
common/json.c

@ -12,7 +12,9 @@
#include <string.h> #include <string.h>
struct json_result { struct json_result {
unsigned int indent; /* tal_arr of types we're enclosed in. */
jsmntype_t *wrapping;
/* tal_count() of this is strlen() + 1 */ /* tal_count() of this is strlen() + 1 */
char *s; char *s;
}; };
@ -365,6 +367,21 @@ static bool result_ends_with(struct json_result *res, const char *str)
return streq(res->s + len - strlen(str), str); return streq(res->s + len - strlen(str), str);
} }
static void check_fieldname(const struct json_result *result,
const char *fieldname)
{
size_t n = tal_count(result->wrapping);
if (n == 0)
/* Can't have a fieldname if not in anything! */
assert(!fieldname);
else if (result->wrapping[n-1] == JSMN_ARRAY)
/* No fieldnames in arrays. */
assert(!fieldname);
else
/* Must have fieldnames in objects. */
assert(fieldname);
}
static void json_start_member(struct json_result *result, const char *fieldname) static void json_start_member(struct json_result *result, const char *fieldname)
{ {
/* Prepend comma if required. */ /* Prepend comma if required. */
@ -372,48 +389,67 @@ static void json_start_member(struct json_result *result, const char *fieldname)
&& !result_ends_with(result, "{ ") && !result_ends_with(result, "{ ")
&& !result_ends_with(result, "[ ")) && !result_ends_with(result, "[ "))
result_append(result, ", "); result_append(result, ", ");
check_fieldname(result, fieldname);
if (fieldname) if (fieldname)
result_append_fmt(result, "\"%s\" : ", fieldname); result_append_fmt(result, "\"%s\" : ", fieldname);
} }
void json_array_start(struct json_result *result, const char *fieldname) static void result_add_indent(struct json_result *result)
{ {
json_start_member(result, fieldname); size_t i, indent = tal_count(result->wrapping);
if (result->indent) {
unsigned int i; if (!indent)
return;
result_append(result, "\n"); result_append(result, "\n");
for (i = 0; i < result->indent; i++) for (i = 0; i < indent; i++)
result_append(result, "\t"); result_append(result, "\t");
} }
static void result_add_wrap(struct json_result *result, jsmntype_t type)
{
size_t indent = tal_count(result->wrapping);
tal_resize(&result->wrapping, indent+1);
result->wrapping[indent] = type;
}
static void result_pop_wrap(struct json_result *result, jsmntype_t type)
{
size_t indent = tal_count(result->wrapping);
assert(indent);
assert(result->wrapping[indent-1] == type);
tal_resize(&result->wrapping, indent-1);
}
void json_array_start(struct json_result *result, const char *fieldname)
{
json_start_member(result, fieldname);
result_add_indent(result);
result_append(result, "[ "); result_append(result, "[ ");
result->indent++; result_add_wrap(result, JSMN_ARRAY);
} }
void json_array_end(struct json_result *result) void json_array_end(struct json_result *result)
{ {
assert(result->indent);
result->indent--;
result_append(result, " ]"); result_append(result, " ]");
result_pop_wrap(result, JSMN_ARRAY);
} }
void json_object_start(struct json_result *result, const char *fieldname) void json_object_start(struct json_result *result, const char *fieldname)
{ {
json_start_member(result, fieldname); json_start_member(result, fieldname);
if (result->indent) { result_add_indent(result);
unsigned int i;
result_append(result, "\n");
for (i = 0; i < result->indent; i++)
result_append(result, "\t");
}
result_append(result, "{ "); result_append(result, "{ ");
result->indent++; result_add_wrap(result, JSMN_OBJECT);
} }
void json_object_end(struct json_result *result) void json_object_end(struct json_result *result)
{ {
assert(result->indent);
result->indent--;
result_append(result, " }"); result_append(result, " }");
result_pop_wrap(result, JSMN_OBJECT);
} }
void json_add_num(struct json_result *result, const char *fieldname, unsigned int value) void json_add_num(struct json_result *result, const char *fieldname, unsigned int value)
@ -498,13 +534,13 @@ struct json_result *new_json_result(const tal_t *ctx)
/* Using tal_arr means that it has a valid count. */ /* Using tal_arr means that it has a valid count. */
r->s = tal_arrz(r, char, 1); r->s = tal_arrz(r, char, 1);
r->indent = 0; r->wrapping = tal_arr(r, jsmntype_t, 0);
return r; return r;
} }
const char *json_result_string(const struct json_result *result) const char *json_result_string(const struct json_result *result)
{ {
assert(!result->indent); assert(tal_count(result->wrapping) == 0);
assert(tal_count(result->s) == strlen(result->s) + 1); assert(tal_count(result->s) == strlen(result->s) + 1);
return result->s; return result->s;
} }

Loading…
Cancel
Save