Search code examples
pythonsqljsonpython-3.10structural-pattern-matching

How use pattern matching for SQL style queries against JSON or JSON lines


Starting with data in the form of JSON or JSON lines, I want to use structural pattern matching to run queries against it.

For example, after running json.load() I get a dict structured like this:

publications = {
    'location': 'central library',
    'items': [
        {'kind': 'book', 'title': 'Python in Aviation'},
        {'kind': 'magazine', 'title': 'Flying Monthly', 'issues': 15},
        {'kind': 'book', 'title': 'Python for Rock Climbers'},
        {'kind': 'magazine', 'title': 'Weekly Climber', 'issues': 42},        
    ]
}

What I want to do is apply Python 3.10's structural pattern matching extract relevant data much like I would with this SQL query:

SELECT title, issues FROM Publications WHERE kind = "magazine";

Solution

  • Mapping Patterns

    The key to the solution is to apply mapping patterns. Per PEP 634, they have the form:

    mapping_pattern: '{' [items_pattern] '}'
    items_pattern: ','.key_value_pattern+ ','?
    key_value_pattern:
        | (literal_pattern | value_pattern) ':' pattern
        | double_star_pattern
    double_star_pattern: '**' capture_pattern
    

    In everyday language, this means "write a dictionary with curly braces putting in constants for values you want to match on and putting in variables for the fields you want to extract."

    Worked-out example

    Using the data supplied in the question, here is how you would translate the requested SQL query:

    for item in publications['items']:
        match item:
            case {'kind': 'magazine', 'title': title, 'issues': issues}:
                print(f'{title} has {issues} issues on hand')
    

    This filters items to only include magazines. Then it extracts the title and issues fields. This outputs:

    Flying Monthly has 15 issues on hand
    Weekly Climber has 42 issues on hand