+ fputs("{\n", data->fh);
+ data->level++;
+
+ print_indent(data->level, data->fh);
+ fputs("\"filtered\": ", data->fh);
+ fputs("\"", data->fh);
+ print_escaped_json(data->fh, json_key);
+ fputs("\"\n", data->fh);
+
+ data->level--;
+ print_indent(data->level, data->fh);
+ fputs("}", data->fh);
+}
+
+/**
+ * Writes the hex dump of a node. A json array is written containing the hex dump, position, length, bitmask and type of
+ * the node.
+ */
+static void
+write_json_proto_node_hex_dump(proto_node *node, write_json_data *data)
+{
+ field_info *fi = node->finfo;
+
+ fputs("[\"", data->fh);
+
+ if (fi->hfinfo->bitmask!=0) {
+ switch (fi->value.ftype->ftype) {
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ fprintf(data->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
+ break;
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ fprintf(data->fh, "%X", fvalue_get_uinteger(&fi->value));
+ break;
+ case FT_INT40:
+ case FT_INT48:
+ case FT_INT56:
+ case FT_INT64:
+ fprintf(data->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
+ break;
+ case FT_UINT40:
+ case FT_UINT48:
+ case FT_UINT56:
+ case FT_UINT64:
+ case FT_BOOLEAN:
+ fprintf(data->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ json_write_field_hex_value(data, fi);
+ }
+
+ /* Dump raw hex-encoded dissected information including position, length, bitmask, type */
+ fprintf(data->fh, "\", %" G_GINT32_MODIFIER "d", fi->start);
+ fprintf(data->fh, ", %" G_GINT32_MODIFIER "d", fi->length);
+ fprintf(data->fh, ", %" G_GUINT64_FORMAT, fi->hfinfo->bitmask);
+ fprintf(data->fh, ", %" G_GINT32_MODIFIER "d", (gint32)fi->value.ftype->ftype);
+
+ fputs("]", data->fh);
+}
+
+/**
+ * Writes the children of a node. Calls write_json_proto_node_list internally which recursively writes children of nodes
+ * to the output.
+ */
+static void
+write_json_proto_node_children(proto_node *node, write_json_data *data)
+{
+ GSList *same_key_nodes_list = json_proto_node_children_grouper(node);
+ write_json_proto_node_list(same_key_nodes_list, data);
+ g_slist_free(same_key_nodes_list);
+}
+
+/**
+ * Writes the value of a node to the output.
+ */
+static void
+write_json_proto_node_value(proto_node *node, write_json_data *data)
+{
+ field_info *fi = node->finfo;
+ // Get the actual value of the node as a string.
+ char *value_string_repr = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
+
+ fputs("\"", data->fh);
+ print_escaped_json(data->fh, value_string_repr);
+ fputs("\"", data->fh);
+
+ wmem_free(NULL, value_string_repr);
+}
+
+/**
+ * Write the value for a node that has no value and no children. This is the empty string for all nodes except those of
+ * type FT_PROTOCOL for which the full name is written instead.
+ */
+static void
+write_json_proto_node_no_value(proto_node *node, write_json_data *data)
+{
+ field_info *fi = node->finfo;
+
+ fputs("\"", data->fh);
+
+ if (fi->hfinfo->type == FT_PROTOCOL) {
+ if (fi->rep) {
+ print_escaped_json(data->fh, fi->rep->representation);