Moved the json_object iteration into its own function, so that it can be called recursively. This made us able to do just that, and easily handle nested objects. Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- modules/jsonparser/jsonparser.c | 112 ++++++++++++++++++++++----------------- 1 files changed, 64 insertions(+), 48 deletions(-) diff --git a/modules/jsonparser/jsonparser.c b/modules/jsonparser/jsonparser.c index 74e83a8..24249f9 100644 --- a/modules/jsonparser/jsonparser.c +++ b/modules/jsonparser/jsonparser.c @@ -44,80 +44,96 @@ log_json_parser_set_prefix (LogParser *p, const gchar *prefix) self->prefix = g_strdup (prefix); } -static gboolean -log_json_parser_process (LogParser *s, LogMessage *msg, const gchar *input) +static void +log_json_parser_process_object (struct json_object *jso, + const gchar *prefix, + LogMessage *msg) { - LogJSONParser *self = (LogJSONParser *) s; - struct json_object *jso; struct json_object_iter itr; ScratchBuffer *key, *value; - jso = json_tokener_parse (input); - key = scratch_buffer_acquire (); value = scratch_buffer_acquire (); - if (!jso) - { - msg_error ("Unparsable JSON stream encountered", NULL); - return FALSE; - } - json_object_object_foreachC (jso, itr) { gboolean parsed = FALSE; switch (json_object_get_type (itr.val)) - { - case json_type_boolean: - msg_info ("JSON parser does not support boolean types yet, skipping", - evt_tag_str ("key", itr.key), NULL); - break; - case json_type_double: - parsed = TRUE; + { + case json_type_boolean: + msg_info ("JSON parser does not support boolean types yet, skipping", + evt_tag_str ("key", itr.key), NULL); + break; + case json_type_double: + parsed = TRUE; g_string_printf (sb_string (value), "%f", json_object_get_double (itr.val)); - break; - case json_type_int: - parsed = TRUE; + break; + case json_type_int: + parsed = TRUE; g_string_printf (sb_string (value), "%i", json_object_get_int (itr.val)); - break; - case json_type_string: - parsed = TRUE; + break; + case json_type_string: + parsed = TRUE; g_string_assign (sb_string (value), json_object_get_string (itr.val)); - break; - case json_type_object: - case json_type_array: - msg_error ("JSON parser does not support objects and arrays yet, " - "skipping", - evt_tag_str ("key", itr.key), NULL); - break; - default: - msg_error ("JSON parser encountered an unknown type, skipping", - evt_tag_str ("key", itr.key), NULL); - break; - } + break; + case json_type_object: + g_string_assign (sb_string (key), prefix); + g_string_append (sb_string (key), itr.key); + g_string_append_c (sb_string (key), '.'); + log_json_parser_process_object (itr.val, sb_string (key)->str, msg); + break; + case json_type_array: + msg_error ("JSON parser does not support arrays yet, " + "skipping", + evt_tag_str ("key", itr.key), NULL); + break; + default: + msg_error ("JSON parser encountered an unknown type, skipping", + evt_tag_str ("key", itr.key), NULL); + break; + } if (parsed) - { - if (self->prefix) - { - g_string_assign (sb_string (key), self->prefix); + { + if (prefix) + { + g_string_assign (sb_string (key), prefix); g_string_append (sb_string (key), itr.key); - log_msg_set_value (msg, + log_msg_set_value (msg, log_msg_get_value_handle (sb_string (key)->str), sb_string (value)->str, sb_string (value)->len); - } - else - log_msg_set_value (msg, - log_msg_get_value_handle (itr.key), - sb_string (value)->str, sb_string (value)->len); - } + } + else + log_msg_set_value (msg, + log_msg_get_value_handle (itr.key), + sb_string (value)->str, sb_string (value)->len); + } } scratch_buffer_release (key); scratch_buffer_release (value); +} + +static gboolean +log_json_parser_process (LogParser *s, LogMessage *msg, const gchar *input) +{ + LogJSONParser *self = (LogJSONParser *) s; + struct json_object *jso; + struct json_object_iter itr; + + jso = json_tokener_parse (input); + + if (!jso) + { + msg_error ("Unparsable JSON stream encountered", NULL); + return FALSE; + } + + log_json_parser_process_object (jso, self->prefix, msg); + json_object_put (jso); return TRUE; -- 1.7.7.3