DEV Community

Liam Martin
Liam Martin

Posted on

How to Parse and Filter Large JSON Files in Python

Working with JSON data is a daily task for most backend developers. However, when you start dealing with massive JSON files (think gigabytes of data from API dumps or system logs), using the standard json.load() method can quickly consume all your available RAM and crash your application.

Recently, I had to process a 4GB JSON file containing thousands of nested records. Instead of loading the entire file into memory, I used Python generators to parse and filter the data efficiently.

Here is a quick breakdown of how to handle large JSON datasets without hitting memory limits.

The Memory Problem

Normally, parsing a JSON file in Python looks like this:

import json

def load_bad_way(file_path):
    with open(file_path, 'r') as file:
        # This loads the entire file into RAM at once
        data = json.load(file)
        return data
Enter fullscreen mode Exit fullscreen mode

If file_path points to a file that is larger than your available memory, your script will throw a MemoryError and terminate.

The Generator Solution

To process the data efficiently, we can read the file line by line (assuming it's a JSON Lines format, or .jl), parse each line individually, and yield the result. This keeps our memory footprint extremely low, regardless of the file size.

Here is the script I use for iterative parsing and filtering:

import json

def process_large_json(file_path, filter_keyword):
    """
    Reads a large JSON file line by line and yields records 
    that contain the specified filter_keyword.
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            for line in file:
                # Parse the single line into a Python dictionary
                record = json.loads(line.strip())

                # Apply your filtering logic here
                if record.get('status') == filter_keyword:
                    yield record

    except FileNotFoundError:
        print(f"Error: The file {file_path} was not found.")
    except json.JSONDecodeError:
        print("Error: Invalid JSON format encountered.")

# Example usage
if __name__ == "__main__":
    DATA_FILE = "system_logs.json"

    print("Extracting active records...")

    # The generator only processes one record at a time
    active_records = process_large_json(DATA_FILE, filter_keyword="active")

    # Iterate through the filtered results
    for valid_record in active_records:
        print(f"Found record ID: {valid_record.get('id')}")
Enter fullscreen mode Exit fullscreen mode

Why This Works

By using the yield keyword, process_large_json becomes a generator. It pauses execution, returns the current record to the for loop, and waits to be called again before reading the next line from the file.

The memory consumption remains flat because Python only holds a single string (the current line) and a single dictionary (the parsed record) in memory at any given time.

How do you usually handle massive datasets in your backend applications? Do you prefer Python generators or do you rely on external tools like jq? Let me know your workflow in the comments!

Top comments (2)

Collapse
 
readyrobert profile image
Robert

Thank you! It helped me a lot, I was looking for this

Collapse
 
liammartin profile image
Liam Martin

I'm glad it helped, Robert. And thanks for your comment!