Skip to content

fix: Handle unhashable BooleanField representation value#9973

Open
emfpdlzj wants to merge 1 commit into
encode:mainfrom
emfpdlzj:fix/booleanfield-unhashable-representation
Open

fix: Handle unhashable BooleanField representation value#9973
emfpdlzj wants to merge 1 commit into
encode:mainfrom
emfpdlzj:fix/booleanfield-unhashable-representation

Conversation

@emfpdlzj
Copy link
Copy Markdown

This is a small consistency fix for BooleanField.to_representation(), matching the existing TypeError handling used by to_internal_value() while preserving the existing bool(value) fallback.

Summary

BooleanField.to_representation() now handles unhashable values consistently with to_internal_value().

Previously, values like [], {}, or set() could raise TypeError during membership checks before reaching the existing bool(value) fallback. This change suppresses TypeError around the explicit true/false/null token checks, allowing unrecognized unhashable values to be represented by their truthiness.

Test

  • Added BooleanField representation coverage for empty and non-empty unhashable collection values.
  • Ran:
    uv run --no-project --with 'django==5.2.*' --with 'pytest==9.*' --with pytest-django --with dj-database-url --with importlib-metadata --with pytz -m pytest tests/test_fields.py -k BooleanField

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes BooleanField.to_representation() resilient to unhashable values (e.g., [], {}, set()) by suppressing TypeError during membership checks, aligning its behavior with to_internal_value() while preserving the existing bool(value) fallback.

Changes:

  • Wrap BooleanField.to_representation()’s TRUE/FALSE/NULL token membership checks in contextlib.suppress(TypeError).
  • Update BooleanField output tests to use a list of (value, expected) pairs (allowing unhashable test inputs) and add coverage for unhashable collections.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
rest_framework/fields.py Suppresses TypeError during set-membership checks in BooleanField.to_representation() so unhashable values fall back to bool(value).
tests/test_fields.py Extends BooleanField representation coverage to include unhashable collections by switching outputs to tuple-pairs and adding new cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Natgho
Copy link
Copy Markdown
Contributor

Natgho commented Jun 3, 2026

PR seems reasonable and appropriate.

Only a potential edge-case scenario might be cause for concern;

Let's say that, either by mistake or due to a custom library integration, a complex custom object that cannot be converted to a string or whose type cannot be checked was passed to the to_representation method:

Old Behavior: The code raised a TypeError and crashed (the API returned a 500 error).

New Behavior: The code does not crash; instead, it passes the object through the bool(object) filter. Since all non-empty or non-None custom objects in Python return True by default, the API now returns the True value as JSON without crashing.

However, this is simply a bug fix that needed to be addressed anyway. That’s why I think it’s acceptable.

@browniebroke
Copy link
Copy Markdown
Member

This is a small consistency fix for BooleanField.to_representation(), matching the existing TypeError handling used by to_internal_value() while preserving the existing bool(value) fallback.

Taking a step back away from the model field itself, what concrete example would cause that from being used? I'm thinking of a minimal example of a serializer with the data/Python object that would make use of this. I think we would need to map a complex field (e.g. dict) to a BooleanField?

@Natgho
Copy link
Copy Markdown
Contributor

Natgho commented Jun 3, 2026

This is a small consistency fix for BooleanField.to_representation(), matching the existing TypeError handling used by to_internal_value() while preserving the existing bool(value) fallback.

Taking a step back away from the model field itself, what concrete example would cause that from being used? I'm thinking of a minimal example of a serializer with the data/Python object that would make use of this. I think we would need to map a complex field (e.g. dict) to a BooleanField?

Yes, actually, this is more of an improvement aimed at preventing the “representation” step from crashing. As it stands now, the system crashes when dealing with a complex variable type because there is no mechanism to handle this situation. This code prevents that error and manages this part using a boolean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants