Zero is a real constraint, not an absent value.
Django REST Framework’s built-in OpenAPI mapper translates serializer field limits into schema properties such as minimum and maximum. For numeric child fields inside a ListField, values of 0 and 0.0 were omitted even though they were explicitly configured.
PR #9977, authored by Zain Nadeem after discussion #9976, corrected this distinction for integer and floating-point bounds.
Truthiness conflated zero with no value.
The helper responsible for mapping limits used conditions equivalent to if field.min_value and if field.max_value. In Python, numeric zero is false in a boolean context, so the mapper skipped a valid boundary. Positive and negative non-zero values continued to work, which made the defect specific to the boundary most likely to expose a truthiness check.
min_value = 0bool(0) == False → omitTest for absence explicitly.
The patch changes both conditions to is not None. That preserves zero-valued constraints while continuing to omit fields whose limits are genuinely unspecified.
if field.max_value is not None:
content["maximum"] = field.max_value
if field.min_value is not None:
content["minimum"] = field.min_valueCover both numeric types and both bound directions.
The regression matrix adds IntegerField and FloatField children with zero minimums and zero maximums. Each expected schema retains the correct minimum or maximum property inside the list’s items schema. The PR record documents focused and broader OpenAPI test runs; skipped cases were attributed to an optional local dependency rather than presented as executed coverage.
Presence checks and truth checks encode different contracts.
- Use explicit sentinel checks when zero, empty strings, or empty collections are valid domain values.
- Boundary-value tests should cover both sides of a mapping: minimum and maximum, integer and float.
- Generated schemas are public interfaces; losing a constraint can mislead clients even when runtime validation remains correct.