How to Implement Sparse Fieldsets in Python

A function that filters API responses by resource type, returning only requested fields plus IDs, as a sparse fieldset mock.

Easy Python 3.9+ Aug 9, 2026 API design & gRPC 12 views 0 copies

Python code

70 lines
Python 3.9+
from dataclasses import dataclass, field
from typing import Dict, List, Optional


@dataclass
class MockResponse:
    data: Dict[str, object] = field(default_factory=dict)
    included: List[Dict[str, object]] = field(default_factory=list)


def select_fields(
    data: Dict[str, object],
    sparse_fields: Optional[Dict[str, List[str]]] = None
) -> MockResponse:
    """
    Mock sparse fieldset selection from a full data object.
    Filters fields per resource type based on requested fields.
    """
    if not sparse_fields:
        return MockResponse(data=data)

    selected_data = {}
    included_records = []

    # Process primary data
    resource_type = data.get("type", "")
    requested_fields = sparse_fields.get(resource_type)

    if requested_fields is not None:
        selected_data = {
            field_name: data[field_name]
            for field_name in data
            if field_name in requested_fields or field_name == "id"
        }
    else:
        selected_data = dict(data)

    # Process related included records
    for related in data.get("relationships", {}).values():
        link_data = related.get("data")
        if isinstance(link_data, list):
            for record in link_data:
                record_type = record["type"]
                record_fields = sparse_fields.get(record_type)
                if record_fields is not None:
                    filtered = {
                        k: v for k, v in record.items()
                        if k in record_fields or k == "id"
                    }
                    included_records.append(filtered)
                else:
                    included_records.append(record)

    return MockResponse(data=selected_data, included=included_records)


if __name__ == "__main__":
    full_data = {
        "type": "articles",
        "id": "1",
        "title": "JSON:API paints my bikeshed!",
        "body": "Shortest article ever.",
        "author": {"data": {"type": "people", "id": "42"}}
    }

    sparse = {"articles": ["title"], "people": ["name"]}

    result = select_fields(full_data, sparse)
    print("Selected data:", result.data)
    print("Included records:", result.included)

Output

stdout
Selected data: {'type': 'articles', 'id': '1', 'title': 'JSON:API paints my bikeshed!'}
Included records: [{'type': 'people', 'id': '42'}]

How it works

This implementation mimics JSON:API sparse fieldsets by filtering a full response object down to only the requested fields. The select_fields function checks the top-level resource type and applies the requested field list, always preserving the id. It then iterates through relationships to filter included records by their own type. The MockResponse dataclass stores the processed data and included records cleanly. Using dictionaries and list comprehensions keeps the filtering logic concise and readable.

Common mistakes

  • Filtering out the 'id' field when it wasn't explicitly requested
  • Assuming all related records have a 'type' key without checking
  • Forgetting to handle relationship data that's a single object instead of a list

Variations

  1. Use a recursive function to handle deeply nested relationships
  2. Return a plain dictionary instead of a dataclass wrapper

Real-world use cases

  • Building a mock API client for frontend development where the backend isn't ready yet.
  • Unit testing your app's data-parsing logic by simulating partial API responses.
  • Prototyping API consumers that depend on the sparse fieldsets feature of JSON:API-compliant services.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.