Nested-multipart-parser
Parser for nested data for multipart/form, usable in any Python project or via the Django Rest Framework integration..
Installation:
pip install nested-multipart-parser
Usage:
from nested_multipart_parser import NestedParser
options = {
"separator": "bracket"
}
def my_view():
# `options` is optional
parser = NestedParser(data, options)
if parser.is_valid():
validate_data = parser.validate_data
...
else:
print(parser.errors)
Django Rest Framework
you can define parser for all view in settings.py
REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES": [
"nested_multipart_parser.drf.DrfNestedParser",
]
}
or directly in your view
from nested_multipart_parser.drf import DrfNestedParser
...
class YourViewSet(viewsets.ViewSet):
parser_classes = (DrfNestedParser,)
What it does:
The parser takes the request data and transforms it into a Python dictionary.
example:
# input:
{
'title': 'title',
'date': "time",
'simple_object.my_key': 'title'
'simple_object.my_list[0]': True,
'langs[0].id': 666,
'langs[0].title': 'title',
'langs[0].description': 'description',
'langs[0].language': "language",
'langs[1].id': 4566,
'langs[1].title': 'title1',
'langs[1].description': 'description1',
'langs[1].language': "language1"
}
# result:
{
'title': 'title',
'date': "time",
'simple_object': {
'my_key': 'title',
'my_list': [
True
]
},
'langs': [
{
'id': 666,
'title': 'title',
'description': 'description',
'language': 'language'
},
{
'id': 4566,
'title': 'title1',
'description': 'description1',
'language': 'language1'
}
]
}
How it works
Lists
Attributes whose sub‑keys are only numbers become Python lists:
data = {
'title[0]': 'my-value',
'title[1]': 'my-second-value'
}
output = {
'title': [
'my-value',
'my-second-value'
]
}
Important notes
- Indices must be contiguous and start at 0.
- You cannot turn a primitive (int, bool, str) into a list later, e.g.
'title': 42,
'title[object]': 42 # ❌ invalid
Dictionaries
Attributes whose sub‑keys are not pure numbers become nested dictionaries:
data = {
'title.key0': 'my-value',
'title.key7': 'my-second-value'
}
output = {
'title': {
'key0': 'my-value',
'key7': 'my-second-value'
}
}
Chaining keys
Keys can be chained arbitrarily. Below are examples for each separator option:
| Separator | Example key | Meaning |
|---|---|---|
| mixed‑dot | the[0].chained.key[0].are.awesome[0][0] | List → object → list → object … |
| mixed | the[0]chained.key[0]are.awesome[0][0] | Same as mixed‑dot but without the dot after a list |
| bracket | the[0][chained][key][0][are][awesome][0][0] | Every sub‑key is wrapped in brackets |
| dot | the.0.chained.key.0.are.awesome.0.0 | Dots separate every level; numeric parts become lists |
Rules to keep in mind
- First key must exist – e.g. title[0] or just title.
- For mixed / mixed‑dot, [] denotes a list and . denotes an object.
- mixed‑dot behaves like mixed but inserts a dot when an object follows a list.
- For bracket, each sub‑key must be surrounded by brackets ([ ]).
- For bracket or dot, numeric sub‑keys become list elements; non‑numeric become objects.
- No spaces between separators.
- By default, duplicate keys are disallowed (see options).
- Empty structures are supported: Empty list → "article.authors[]": None → {"article": {"authors": []}} Empty dict → "article.": None → {"article": {}} (available with dot, mixed, mixed‑dot)
Options
{
# Separator (default: 'mixed‑dot')
# mixed‑dot : article[0].title.authors[0] -> "john doe"
# mixed : article[0]title.authors[0] -> "john doe"
# bracket : article[0][title][authors][0] -> "john doe"
# dot : article.0.title.authors.0 -> "john doe"
'separator': 'bracket' | 'dot' | 'mixed' | 'mixed‑dot',
# Raise an exception when duplicate keys are encountered
# Example:
# {
# "article": 42,
# "article[title]": 42,
# }
'raise_duplicate': True, # default: True
# Override duplicate keys (requires raise_duplicate=False)
# Example:
# {
# "article": 42,
# "article[title]": 42,
# }
# Result:
# {
# "article": {
# "title": 42
# }
# }
'assign_duplicate': False, # default: False
}
Options for Django Rest Framwork:
# settings.py
...
# settings.py
DRF_NESTED_MULTIPART_PARSER = {
"separator": "mixed‑dot",
"raise_duplicate": True,
"assign_duplicate": False,
# If True, the parser’s output is converted to a QueryDict;
# if False, a plain Python dict is returned.
"querydict": True,
}
JavaScript integration:
A companion multipart-object library exists to convert a JavaScript object into the flat, nested format expected by this parser.
License
Metadata
Release files for nested-multipart-parser 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| nested_multipart_parser-1.6.0.tar.gz | 13.2 kB | Without provenance | Details |
Release files / nested_multipart_parser-1.6.0.tar.gz
| Download URL | nested_multipart_parser-1.6.0.tar.gz |
|---|---|
| Size | 13.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c7a07952a4a3c2cb2b99ca16158961af215c6f8c9e04337bc13da016500c69c
|
|
BLAKE2b-256 checksum How to use checksums |
b848b91a6f924a2abd9e86b501347ca56989e2c2b4bf3eac86bff57f80b99b75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Security for nested-multipart-parser 1.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.