Skip to content

Preserve leading-zero JSON keys in nested items - #1956

Closed
harsh-thakkar7 wants to merge 2 commits into
httpie:masterfrom
harsh-thakkar7:fix/preserve-leading-zero-json-keys
Closed

harsh-thakkar7 wants to merge 2 commits into
httpie:masterfrom
harsh-thakkar7:fix/preserve-leading-zero-json-keys

Conversation

@harsh-thakkar7

Copy link
Copy Markdown

Summary

A nested JSON item with a leading-zero literal, e.g. 01=x, was tokenized as a NUMBER (Python's int('01') β†’ 1) and emitted as the key "1" β€” silently rewriting the key and colliding with a real 1=x item, losing data:

$ http example.com/post '01=x' '1=y'
{"1": "y"}     # '01' became '1' and overwrote '1'!

01 is a valid JSON key; JSON numbers cannot have leading zeros, so coercing it to an integer is lossy.

Fix

In httpie/cli/nested_json/parse.py, only treat a literal as a number when it is canonical β€” i.e. its str() form round-trips exactly (int(value) without leading zeros / missing sign). Non-canonical literals remain TEXT keys:

def canonical_int(value: str) -> int:
    if not value:
        raise ValueError('Not an int')
    converted = int(value)
    if str(converted) != value:
        raise ValueError('Not a canonical int')
    return converted
$ http example.com/post '01=x' '1=y'
{"01": "x", "1": "y"}    # keys preserved, no collision

Canonical integers are unaffected (kids[0], kids[10], ... still produce numeric array indices).

Tests

  • ['01=x', '1=y'] β†’ {'01': 'x', '1': 'y'} β€” fails before this change (key collapsed to 1).
  • ['kids[0]=Thelma', 'kids[10]=Ashley'] β†’ indices still numeric.
pytest -q tests/test_json.py tests/test_cli_utils.py   # 298 passed

Media types are case-insensitive per RFC 2045 section 5.1, but the
auto-streaming check for Server-Sent Events compared the parsed
Content-Type header literally, so a server responding with e.g.
'Text/Event-Stream' silently fell back to buffered output.
A root literal such as 01=x was tokenized as a NUMBER (int coerces
'01' to 1) and emitted as the key '1', silently rewriting the key and
colliding with a real 1=x item:

    $ http pie.dev/post '01=x' '1=y'
    {1: y}        # '01' became '1' and overwrote '1'!

Only canonical integers (whose str() form matches, i.e. no leading
zeros) are now treated as numbers; JSON keys like '01' are preserved.
@harsh-thakkar7

Copy link
Copy Markdown
Author

Closing this β€” I don't think this change is mature enough to land right now. Thanks for the project!

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