Raymond Hettinger
Raymond Hettinger

Reputation: 226211

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";

Upvotes: 2

Views: 394

Answers (1)

Raymond Hettinger
Raymond Hettinger

Reputation: 226211

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

Upvotes: 1

Related Questions