How should DRF validate polymorphic per-provider JSON payloads before delegating to a service layer?
I'm refactoring a Django/DRF system that ingests skip-trace data from multiple external bureaus (Experian, Equifax, IDI, TLO). Each provider returns a completely different JSON structure. We store the raw payload in a JSONField and normalize parts of it into relational models (DebtorContact, SkipTraceVehicle, SkipTraceProperty).
We've moved from ViewSets to explicit APIView classes plus a service layer that owns the atomic write:
# services.py
class DebtorContactService:
@transaction.atomic
def register_bureau_payload(self, debtor, bureau_type, raw_data):
parsed = self._parse(bureau_type, raw_data)
# bulk_create / bulk_update of normalized records
return contact_record
The payload shape is determined by a bureau_type request parameter. Example (simplified):
// bureau_type = "experian"
{"consumer": {"names": [...], "tradelines": [...]}}
// bureau_type = "tlo"
{"Person": {"Vehicles": [...], "Addresses": [...]}}
A single serializer that branches on bureau_type to validate these deeply nested, structurally unrelated schemas becomes unmaintainable. Options I've tried or considered:
Option A — one endpoint per bureau (/api/skip-trace/experian/, /api/skip-trace/tlo/): clean serializers, but the view logic (auth, debtor lookup, service dispatch, response shape) is duplicated four times.
Option B — one endpoint, runtime serializer selection:
class SkipTracePayloadView(APIView):
SERIALIZERS = {
"experian": ExperianPayloadSerializer,
"tlo": TLOPayloadSerializer,
# ...
}
def post(self, request, debtor_id):
serializer_cls = self.SERIALIZERS.get(request.data.get("bureau_type"))
if serializer_cls is None:
raise ValidationError({"bureau_type": "Unsupported bureau"})
serializer = serializer_cls(data=request.data["payload"])
serializer.is_valid(raise_exception=True)
DebtorContactService().register_bureau_payload(
debtor, request.data["bureau_type"], serializer.validated_data
)
Option C — skip DRF validation entirely and pass raw JSON to the service layer, which validates during parsing (e.g. with dataclasses or pydantic per bureau).
My specific questions:
In Option B, is there a supported DRF mechanism for this dispatch (e.g. overriding
get_serializer_classonGenericAPIViewbased on request data), or is a manual mapping dict inpost()the expected approach forAPIView?If validation moves into the service layer (Option C), what should the serializer still be responsible for, given DRF's design intent that serializers own input validation? Are there concrete drawbacks (error formatting, OpenAPI schema generation, browsable API) to bypassing them for the nested payload?
Django 5.x, DRF 3.15.