Skip to content

Instantly share code, notes, and snippets.

@mschuett

mschuett/flatten_json.py

Last active Apr 10, 2020
Embed
What would you like to do?
convert JSON to Key-Value
#! /usr/bin/env python3
#
# script to convert JSON documents into plain key-value lines,
# formatted to be piped to zabbix_sender
#
# 20130927, martin.schuette@deck36.de
# 20200409, info@mschuette.name, change to Python 3
#
import json
import sys
import types
import os
import argparse
import re
# some formatting
def format_string(s):
if s is None:
return "0"
elif isinstance(s, str) and " " in s:
return '"%s"' % ("\\n".join(s.splitlines()),)
elif isinstance(s, str) and s == "":
return '""'
elif isinstance(s, bool) and s:
return 1
elif isinstance(s, bool) and not s:
return 0
else:
return s
# recursively flatten the document keys:
def flatten_level(doc):
# start with some aux. functions:
def is_leaf(doc):
return not (isinstance(doc, list) or isinstance(doc, dict))
def flatten_list(l):
outlist = []
for (num, sub) in enumerate(l):
if is_leaf(sub):
line = "%s %s" % (num, format_string(sub))
outlist.append(line)
else:
for subitem in flatten_level(sub):
line = "%s.%s" % (num, subitem)
outlist.append(line)
return outlist
def flatten_dict(d):
outlist = []
for (key, sub) in list(d.items()):
if is_leaf(sub):
line = "%s %s" % (key, format_string(sub))
outlist.append(line)
else:
for subitem in flatten_level(sub):
line = "%s.%s" % (key, subitem)
outlist.append(line)
return outlist
if is_leaf(doc):
return format_string(doc)
elif isinstance(doc, list):
return flatten_list(doc)
elif isinstance(doc, dict):
return flatten_dict(doc)
# parse command line arguments:
parser = argparse.ArgumentParser(
description="flatten a JSON document into key-value lines, suitable for Zabbix"
)
parser.add_argument("-p", "--prefix", help="prefix for zabbix keys")
parser.add_argument(
"-a", "--attribute", help="attribute for zabbix keys (e.g. key[attribute])"
)
parser.add_argument(
"-d",
"--dash",
help="prepend every line with a dash, useful to pipe data into zabbix_sender",
action="store_true",
)
parser.add_argument("-f", "--filter", help="field name(s) to filter", action="append")
parser.add_argument(
"-i", "--infile", help="input file", type=argparse.FileType("r"), default=sys.stdin
)
args = parser.parse_args()
# read JSON:
try:
doc = json.load(args.infile)
except ValueError:
# silently fail if input is no valid JSON
sys.exit(1)
# do work:
l = flatten_level(doc)
# filter output:
if args.filter:
for f in args.filter:
l = [x for x in l if not re.search(r"\b" + f, x)]
if args.prefix:
l = [".".join([args.prefix, x]) for x in l]
if args.attribute:
l = [x.replace(" ", "[%s] " % (args.attribute,), 1) for x in l]
if args.dash:
l = ["- " + x for x in l]
print((os.linesep.join(l)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.