Skip to main content

Rugged

An ASGI middleware to unflatten JSON request keys into nested structures.

This behaviour might be familiar if you've used PHP before.

Example use case

The inspiration for this middleware came from a web app with forms that add variable numbers of fields dynamically. This web app uses htmx to submit forms as AJAX requests, and the hx-json-enc extension to send form data as JSON.

For example, with a form like so:

<h1>Your shopping list</h1>
<form method="post" action="/invite" hx-boost="true" hx-ext="json-enc">
    <label>List name <input type="text" name="title"></label>

    <h2>Items</h2>
    <input type="text" name="items[][item]"> x <input type="number" name="items[][qty]" default="1">
    <input type="text" name="items[][item]"> x <input type="number" name="items[][qty]" default="1">
    <input type="text" name="items[][item]"> x <input type="number" name="items[][qty]" default="1">

    <button onclick="addItemFields()">Add item</button>
    <button type="submit">Save</button>
</form>

The request body received by the server could look like this:

{
    "title": "Sofrito time",
    "items[][item]": ["carrots", "celery", "onions"],
    "items[][qty]": [1, 1, 2],
}

Using this middleware, the request body is unflattened into:

{
    "title": "Sofrito time",
    "items": [
        {"item": "carrots", "qty": 1},
        {"item": "celery", "qty": 1},
        {"item": "onions", "qty": 2},
    ],
}

This makes inputs easier to handle in a FastAPI application using Pydantic:

class ShoppingListItem(BaseModel):
    item: str
    qty: int


class ShoppingList(BaseModel):
    title: str
    items: list[ShoppingListItem]


@app.post("/list")
async def invite_users(shopping_list: ShoppingList):
    find_best_prices(shopping_list.items)

A canonical set of supported input names can be found by reading the unit tests for the unflatten() function, as well as the doc-string - docs coming soon!

Usage in starlette and fastapi can be seen in the respective test files, pending documentation.

Contributing & roadmap

  • This middleware is in very early development - things will change. It's being used in a small FastAPI + HTMX microsite.
  • See the roadmap for planned development
  • I am experimenting with Rye to package this project - if you'd like to contribute, the docs are over at rye-up.com

License

This project is released under the terms of the MIT license.

Metadata

Release files for rugged 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rugged 0.2.2
File Size Uploaded Provenance
rugged-0.2.2.tar.gz 9.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for rugged 0.2.2
File Interpreter ABI Platform
rugged-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 17.6 kB

Release files / rugged-0.2.2.tar.gz

Download URL rugged-0.2.2.tar.gz
Size 9.9 kB
Tags Source
SHA-256 checksum
How to use checksums
37650f473ece8bd39a6e495e699ccea692745c7eb045cf193fa699dcf8f42b67
BLAKE2b-256 checksum
How to use checksums
6abcd65e234eb9200f3abf18b95529009e8085bffa6813b1ffc1c0ae3c2a2c8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.8

Release files / rugged-0.2.2-py3-none-any.whl

Download URL rugged-0.2.2-py3-none-any.whl
Size 7.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a4bd448b4e97c046fb0768be3ebb7c4c1c31e2eb1f31262133d5bcd37c026fd
BLAKE2b-256 checksum
How to use checksums
0daf95d20c7c87c311ebf0d36fdc3df70f946bc17b21246068b41e1f62062e6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.8

Security for rugged 0.2.2

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page