diff --git a/rest_framework_dataclasses/serializers.py b/rest_framework_dataclasses/serializers.py index d01d319..72a35e6 100644 --- a/rest_framework_dataclasses/serializers.py +++ b/rest_framework_dataclasses/serializers.py @@ -1,5 +1,6 @@ from __future__ import annotations +import collections import copy import dataclasses import datetime @@ -665,6 +666,23 @@ def to_internal_value(self, data: Dict[str, Any]) -> T: """ native_values = super(DataclassSerializer, self).to_internal_value(data) + # If the source is a wildcard, don't try to instantiate anything, but just return the native values as a dict. + # It'll be merged into the native values of the parent serializer by the parent class. + if self.source == '*': + return native_values + + # If any fields have a wildcard source, their native value will hold a values dictionary instead of a dataclass, + # so convert them into a dataclass. + if any(field.source == '*' for field in self.fields.values()): + for field_name, tp in self.dataclass_definition.field_types.items(): + if ( + field_name in native_values and + dataclasses.is_dataclass(tp) and + isinstance(native_values[field_name], collections.abc.Mapping) + ): + dataclass_fields = {field.name: field for field in dataclasses.fields(tp)} + native_values[field_name] = _create_instance(tp, dataclass_fields, native_values[field_name]) + # Only insert empty sentinel value for non-supplied values when the root serializer is in partial mode, to # prevent them from showing up otherwise. if self.root.partial: