ResponseAdapter

Pluggable response-extraction strategy for ApiBackend.

  1. Overview

Overview

Sits between execute_request() returning the raw response JSON and the map_to_model pipeline. Its sole responsibility is answering the structural question — where is the data inside the envelope? — leaving the field-level question (column name mapping, casing, etc.) to api_to_model_map and map_to_model as before.

Implementing a custom adapter

Subclass ResponseAdapter and override either/both methods. Return None from either method to signal “I cannot handle this shape; fall through to the built-in ApiBackend logic”:

import clearskies


class MyServiceResponseAdapter(clearskies.backends.ResponseAdapter):
    def extract_records(self, response_data):
        # unwrap {"results": [...]}
        return response_data.get("results")

    def extract_record(self, response_data):
        # unwrap {"item": {...}}
        return response_data.get("item")

Attach it to an ApiBackend subclass (or directly to an instance):

class MyServiceBackend(clearskies.backends.ApiBackend):
    def __init__(self):
        super().__init__(
            base_url="https://api.example.com",
            response_adapter=MyServiceResponseAdapter(),
        )

Using a callable

For simple cases a plain callable may be supplied instead of a full subclass. The callable receives the raw response data and should return the extracted value, or None to fall through:

backend = clearskies.backends.ApiBackend(
    base_url="https://api.example.com",
    response_adapter=lambda data: data.get("items"),
)

When a callable is provided it is invoked for both extract_records and extract_record calls.