Skip to content

Fix test operation to respect JSON types (boolean vs number) - #187

Open
cognis-digital wants to merge 1 commit into
stefankoegl:masterfrom
cognis-digital:fix/test-op-json-type-equality
Open

Fix test operation to respect JSON types (boolean vs number)#187
cognis-digital wants to merge 1 commit into
stefankoegl:masterfrom
cognis-digital:fix/test-op-json-type-equality

Conversation

@cognis-digital

Copy link
Copy Markdown

What

The test operation currently compares values with a plain !=. Because Python treats bool as a
subclass of int (True == 1, False == 0), a test against the JSON true/false literal
incorrectly succeeds against the numbers 1/0, and vice versa.

import jsonpatch
# Each of these wrongly succeeds today (no JsonPatchTestFailed raised):
jsonpatch.apply_patch({"baz": 1},    [{"op": "test", "path": "/baz", "value": True}])
jsonpatch.apply_patch({"baz": True}, [{"op": "test", "path": "/baz", "value": 1}])
jsonpatch.apply_patch({"baz": 0},    [{"op": "test", "path": "/baz", "value": False}])

Why

RFC 6902 §4.6 defines test equality as requiring the two values to be "of the same JSON type". A
boolean literal and a number are different JSON types and must not compare equal. This mirrors the
intent already present in DiffBuilder._compare_values, which uses json.dumps specifically so it
can "recognize the difference between 1 and True".

How

Adds a small recursive helper, _compare_json_values, that keeps booleans distinct from numbers,
still compares numbers numerically (1 == 1.0), and recurses into arrays and objects so the rule
also holds for nested values. TestOperation.apply uses it in place of !=. The error type and
message are unchanged; there is no public API change.

Tests

Adds regression tests covering scalar bool/number mismatches in both directions, the 0/false
case, 1/1.0 numeric equality (still passes), same-typed booleans (still pass), and nested
[1] vs [true] / {"q": 1} vs {"q": true} cases. Full suite: 114 passing.

RFC 6902 requires the test operation to only consider values equal when
they are of the same JSON type. Because Python treats bool as a subclass
of int (True == 1, False == 0), a test against the boolean true/false
literal wrongly succeeded against the numbers 1/0 (and vice versa).

Introduce a small recursive equality helper that keeps booleans distinct
from numbers while still comparing numbers numerically (1 == 1.0) and
recursing into arrays and objects. Wire it into TestOperation.apply and
add regression tests.
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.

1 participant