Package: jsonrouter
JSON Events RouterUses simpleyamlbased rules to take action onJSONevents. Usesjsonpathto scan the event message andregexforincludesandexcludesconditionals.Note!jsonroutercurrently converts all matching field values tostrings forregex comparision so be aware of this when expectingintto be returned.Installpip install jsonrouterTL;DRimportjsonimportyamlfromjsonrouterimportJsonMatchEngine# load rules from file or stringconfigs=yaml.load('''rules:- name: example-rulerouters:- name: print-routervars:- name: the-namejsonpath: $.name''')# an example json recordjson_string='''{"name": "jsonrouter","type": "jsonpath matcher and router","why": {"because": "it's easy"}}'''defprint_router(data):# a trivial example router functionprint(json.dumps(data,indent=4))# explicitly declare your registered routers for securityregistered_routers={'print-router':print_router}eng=JsonMatchEngine(configs,registered_routers)Use the engine to find matches:In [2]: matches = eng.route_matches(json_string)
{
    "name": "example-rule",
    "routers": [
        {
            "name": "print-router"
        }
    ],
    "vars": {
        "the-name": "jsonrouter"
    },
    "template": "",
    "record": {
        "name": "jsonrouter",
        "type": "jsonpath matcher and router",
        "why": {
            "because": "it's easy"
        }
    }
}The contents ofmatches:In [3]: matches
Out[3]:
[{'name': 'example-rule',
  'routers': [{'name': 'print-router'}],
  'vars': {'the-name': 'jsonrouter'},
  'template': '',
  'record': {'name': 'jsonrouter',
   'type': 'jsonpath matcher and router',
   'why': {'because': "it's easy"}}}]Rule ConfigAnatomy of the config.# `rules` is the root of the config# note: rules can have same name!rules:# required-name:notification# requiredrouters:# required-name:slack# required# all fields besides name are optional but may be required in the routerchannel:my-channel# optionalvars:# required-name:type# requiredjsonpath:$..Type# required, except for constants: see bellowincludes:['.*']# optional, default `['.*']` includes allexcludes:[]# optional, default `[]` excludes nothing# `template` is optionaltemplate:|This {type} just came inConstantsYou can define a constant var by providingvaluefield onlyvars:-name:my-constantvalue:my constant valueBasic UsageSimple capture examples.rules:-name:notificationrouters:-name:slackchannel:my-channelvars:-name:typejsonpath:$..Type# include anythingincludes:['.*']# exclude emptyexcludes:['^$']template:|This {type} just came inAdvanced RegexMatch Part of String()rules:-name:console_loginrouters:-name:slackchannel:my-channelvars:-name:detail-typejsonpath:$..detail-typeincludes:['AWSConsoleSignInviaCloudTrail']excludes:['^$']-name:userjsonpath:$..principalId# Match part of stringincludes:['.*:(.*)']excludes:['^$']-name:accountjsonpath:$..accountincludes:['.*']excludes:['^$']template:|Yo! {user} just signed in to {account}.Match in String with Group NameUse(?P<variable_name>)to capture patterns within the matched field.This will override any naming collisions withvars:nameyou set in the yaml. It merges the rule vars with matched name(s) declared in the regex where named regex take precedencerules:-name:console_loginrouters:-name:slackchannel:my-channelvars:-name:detail-typejsonpath:$..detail-typeincludes:['AWSConsoleSignInviaCloudTrail']excludes:['^$']-name:userjsonpath:$..principalId# Match part of string with variable namesincludes:['(?P<stuff>.*):(?P<user>.*)']excludes:['^$']-name:accountjsonpath:$..accountincludes:['.*']excludes:['^$']template:|Yo! {user} just signed in to {account}. This {stuff} was before the user.Lambda ExampleSincejsonrouterstarted from an AWS Lambda SNS parsing project it has ajsonify_stringmethod that converts the SNS message field from a sting to a nesteddict.importjsonimportyamlfromjsonrouterimportJsonMatchEngine,jsonify_stringdefslack(webhook):# whatever logic you want in herepasswithopen('rules.yaml','r')asf:configs=yaml.safe_load(f)registered_routers={'slack':slack}eng=JsonMatchEngine(configs,registered_routers)defhandler(event,context):# Main lambda handler functioneng.route_matches(jsonify_string(event)['Records'])Development# local tests run from root of project
python3 -m pytest -v
# to see print output use `-s`
python3 -m pytest -v -s