QueryString parser for Python/Django that correctly handles nested dictionaries
npx @tessl/cli install tessl/pypi-querystring-parser@1.2.0A Python library that parses query strings into nested dictionaries, handling complex bracket notation that Django's standard QueryDict treats as literal strings. Converts form data like section[0]['words'][2]=value into proper nested Python dictionaries for easier data manipulation.
pip install querystring_parsersix (Python 2/3 compatibility)from querystring_parser import parser
from querystring_parser import builderIndividual function imports:
from querystring_parser.parser import parse, MalformedQueryStringError
from querystring_parser.builder import buildfrom querystring_parser import parser
# Parse a query string with nested parameters
query_string = "section[1]['words'][2]=a§ion[0]['words'][2]=a§ion[0]['words'][2]=b"
result = parser.parse(query_string)
# Output: {u'section': {0: {u'words': {2: [u'a', u'b']}}, 1: {u'words': {2: u'a'}}}}
print(result)
# Convert back to query string
from querystring_parser import builder
rebuilt_query = builder.build(result)
print(rebuilt_query)Converts query strings with bracket notation into nested Python dictionaries, properly handling arrays and nested structures.
def parse(query_string, unquote=True, normalized=False, encoding=DEFAULT_ENCODING):
"""
Parse query string into nested dictionary structure.
Parameters:
- query_string (str|bytes): Query string to parse
- unquote (bool): Whether to URL-decode the query string (default: True)
- normalized (bool): Convert numeric dict keys to proper lists (default: False)
- encoding (str|None): Encoding for decoding keys/values (default: DEFAULT_ENCODING)
Returns:
dict: Nested dictionary representing parsed query string
Raises:
MalformedQueryStringError: When query string is malformed
"""Usage Examples:
from querystring_parser.parser import parse
# Basic parsing
result = parse("name=John&age=30")
# Returns: {'name': 'John', 'age': '30'}
# Nested structures
result = parse("user[name]=John&user[details][age]=30")
# Returns: {'user': {'name': 'John', 'details': {'age': '30'}}}
# Array handling
result = parse("items[0]=apple&items[1]=banana")
# Returns: {'items': {0: 'apple', 1: 'banana'}}
# Normalized output (converts numeric keys to lists)
result = parse("items[0]=apple&items[1]=banana", normalized=True)
# Returns: {'items': ['apple', 'banana']}
# Custom encoding
result = parse("name=%D8%B9%D9%84%DB%8C", encoding='utf-8')
# Returns: {'name': 'علی'}
# Handle bytes input
result = parse(b"name=John&age=30")
# Returns: {'name': 'John', 'age': '30'}Converts nested Python dictionaries and lists back into query string format with proper bracket notation.
def build(item, encoding=None):
"""
Convert nested dictionary/list structure to query string format.
Parameters:
- item (dict|list): Dictionary or list to convert to query string
- encoding (str|None): Optional encoding for URL encoding (default: None)
Returns:
str: Query string representation of the input structure
"""Usage Examples:
from querystring_parser.builder import build
# Basic dictionary
data = {'name': 'John', 'age': '30'}
result = build(data)
# Returns: "name=John&age=30"
# Nested structures
data = {'user': {'name': 'John', 'details': {'age': '30'}}}
result = build(data)
# Returns: "user[name]=John&user[details][age]=30"
# Lists and arrays
data = {'items': ['apple', 'banana']}
result = build(data)
# Returns: "items=apple&items=banana"
# Mixed nested structures
data = {
'section': {
0: {'words': {2: ['a', 'b']}},
1: {'words': {2: 'c'}}
}
}
result = build(data)
# Returns: "section[0][words][2]=a§ion[0][words][2]=b§ion[1][words][2]=c"
# Custom encoding
data = {'name': 'علی'}
result = build(data, encoding='utf-8')
# Returns: "name=%D8%B9%D9%84%DB%8C"Handles malformed query strings with specific exception for debugging and error recovery.
class MalformedQueryStringError(Exception):
"""
Raised when query string cannot be parsed due to malformed syntax.
Common causes:
- Missing equals sign in key-value pairs
- Unclosed bracket notation
- Invalid bracket syntax
"""Usage Examples:
from querystring_parser.parser import parse, MalformedQueryStringError
try:
# This will raise an exception due to missing equals sign
result = parse("name&age=30", unquote=False)
except MalformedQueryStringError as e:
print(f"Failed to parse query string: {e}")
try:
# This will raise an exception due to unclosed bracket
result = parse("section[0[words]=value", unquote=False)
except MalformedQueryStringError as e:
print(f"Failed to parse query string: {e}")# Module constants
DEFAULT_ENCODING = 'utf-8' # On Python 2, None on Python 3
# Helper functions (internal but potentially useful)
def has_variable_name(s):
"""Check if string has variable name before bracket notation."""
def more_than_one_index(s, brackets=2):
"""Search for multiple sets of bracket pairs."""
def get_key(s):
"""Extract key from between brackets, removing quotes."""
def is_number(s):
"""Check if string represents a number (for array indices)."""
def parser_helper(key, val):
"""Recursive helper for main parse function."""section[0]['words'][2]