mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libutil/util_fmt: Introduce JSON Lines text format
JSON Lines text format (JSONL) [1] is a line-delimited JSON format where objects are separated by the new line character (\n, LF) as opposed to the JSON Sequence text format (json-seq) where JSON text is encapsulated in an ASCII Record Separator (0x1E, RS) and ASCII Line Feed character (0x0A, LF). Whilst JSONL is also used for data streaming, this simpler format is better suited for logging and works also well with traditional line-oriented Unix tooling (e.g. grep or sed). Add this format to util_fmt so that users have more choice and control over formats that are required for their usecases. Add helper functions that let the user determine whether a given format type is JSON in general or a JSON streaming format (such as json-seq or jsonl). For better readability and more clarity use the helper function util_fmt_is_json_stream() where the same decision is made for both JSON streaming formats FMT_JSONSEQ and FMT_JSONL. [1] https://jsonlines.org/ Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
@@ -91,6 +91,7 @@ static const struct {
|
||||
} formats[] = {
|
||||
{ "json", FMT_JSON },
|
||||
{ "json-seq", FMT_JSONSEQ },
|
||||
{ "jsonl", FMT_JSONL },
|
||||
{ "pairs", FMT_PAIRS },
|
||||
{ "csv", FMT_CSV },
|
||||
};
|
||||
@@ -111,6 +112,29 @@ bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool util_fmt_is_json(enum util_fmt_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case FMT_JSON:
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool util_fmt_is_json_stream(enum util_fmt_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void safe_write(const char *str)
|
||||
{
|
||||
size_t done, todo;
|
||||
@@ -129,7 +153,7 @@ static void _indent(unsigned int off, bool safe)
|
||||
{
|
||||
unsigned int num, i;
|
||||
|
||||
if (f.type == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json_stream(f.type))
|
||||
return;
|
||||
num = f.ind_base + off;
|
||||
if (f.type == FMT_JSON && f.lvl > 0)
|
||||
@@ -408,8 +432,8 @@ static void emit_meta_object(void)
|
||||
util_fmt_pair(quoted, "time", "%s", date);
|
||||
_util_fmt_obj_end();
|
||||
|
||||
if (f.type == FMT_JSONSEQ) {
|
||||
/* Tool meta-data is a separate object for JSONSEQ. */
|
||||
if (util_fmt_is_json_stream(f.type)) {
|
||||
/* Tool meta-data is a separate object for JSON streams. */
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
}
|
||||
@@ -478,7 +502,7 @@ void util_fmt_obj_end(void)
|
||||
{
|
||||
_util_fmt_obj_end();
|
||||
|
||||
if (f.lvl == 1 && f.meta_done && f.type != FMT_JSONSEQ) {
|
||||
if (f.lvl == 1 && f.meta_done && !util_fmt_is_json_stream(f.type)) {
|
||||
/* Emit closure for top-level meta-container object. */
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
@@ -737,7 +761,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
|
||||
f.do_warn = (flags & FMT_WARN);
|
||||
f.handle_int = (flags & FMT_HANDLEINT);
|
||||
f.api_level = api_level;
|
||||
if (type == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json_stream(type))
|
||||
f.nl = "";
|
||||
else
|
||||
f.nl = "\n";
|
||||
@@ -750,6 +774,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
|
||||
break;
|
||||
case FMT_JSON:
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
f.obj_start = &json_obj_start;
|
||||
f.obj_end = &json_obj_end;
|
||||
f.map = &json_map;
|
||||
|
||||
@@ -193,6 +193,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
|
||||
announce("JSON formatted as sequence");
|
||||
simple_example(FMT_JSONSEQ, FMT_DEFAULT);
|
||||
|
||||
announce("JSON Lines format");
|
||||
simple_example(FMT_JSONL, FMT_DEFAULT);
|
||||
|
||||
announce("Pairs output");
|
||||
simple_example(FMT_PAIRS, FMT_KEEPINVAL);
|
||||
|
||||
@@ -232,6 +235,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
|
||||
announce("JSON sequence output with meta-data");
|
||||
meta_example(FMT_JSONSEQ);
|
||||
|
||||
announce("JSON Lines output with meta-data");
|
||||
meta_example(FMT_JSONL);
|
||||
|
||||
announce("Pairs output with meta-data");
|
||||
meta_example(FMT_PAIRS);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user