Ok, so Kevin Browns comment is correct. I needed to add allow_null=True.
class SerializerA(serializers.Serializer):
details = DetailsSerializer(required=False, allow_null=True)
The reason for this is that having required=False allows the field details to be absent from the data when constructing the serializer.
e.g.
s = SerializerA(data={})
whereas allow_null permits the the param to be specified but be null.
e.g.
s = SerializerA(data={'details': None})
This opens up another issue with DRF Browsable API, but i’ll ask that in a different question.