Skip to content

Accept array-style keys in from_query_string#577

Open
gaoflow wants to merge 1 commit into
fabiocaccamo:mainfrom
gaoflow:fix/query-string-array-keys
Open

Accept array-style keys in from_query_string#577
gaoflow wants to merge 1 commit into
fabiocaccamo:mainfrom
gaoflow:fix/query-string-array-keys

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 17, 2026

Copy link
Copy Markdown

Problem

from_query_string rejects valid query strings that use array-style keys, which urllib.parse.parse_qs parses without complaint:

from benedict import benedict
benedict.from_query_string("a[]=1&a[]=2")        # ValueError: Invalid query string
benedict.from_query_string("user[name]=joe")     # ValueError: Invalid query string
benedict.from_query_string("items[0]=x&items[1]=y")  # ValueError: Invalid query string

The decode gate in QueryStringSerializer used a hardcoded character whitelist ([\w\-\%\+\.\|]) for keys and values, which omits [ and ] (and other valid characters), so any bracketed/array key fails the gate before parse_qs is ever called. Array-style keys are common (PHP and HTML-form syntax).

Fix

Replace the opaque whitelist with a structural check: split on & and require every segment to be key=value where the key is non-empty and neither side contains raw whitespace, = (key) or &. This accepts bracketed/array keys while still rejecting the other formats benedict's autodetect must distinguish (verified against the repo's own fixtures: TOML, YAML, JSON, XML, plain text and URLs are still rejected).

Tests

Added cases for array-style (a[]=1&a[]=2) and bracketed (user[name]=joe&user[age]=42) keys via both IODict.from_query_string and IODict(s, format="query_string"). Without the fix they raise ValueError; with it the query-string tests pass and the broader IO/serializer suite is green (279 passed locally). ruff check/format clean.

Disclosure: I used AI assistance (Claude) to help locate and draft this fix, under my direction and review.

from_query_string raised ValueError on valid query strings with array-style
keys such as a[]=1&a[]=2 or user[name]=joe. The format gate used a hardcoded
character whitelist that omitted [ and ], so any bracketed key was rejected
before parse_qs was called. Replace the whitelist with a structural check
(each &-segment is key=value with a non-empty key and no raw whitespace),
which accepts bracketed/array keys while still rejecting TOML/YAML/JSON/XML
and plain text.

Adds tests for array-style and bracketed keys.
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