Open KonstantinosPetrakis opened 3 months ago
As the author of the original issue mentioned it most likely has to do something with explode:false
.
There's a dirty monkey patch you can use (the js code was written by ChatGPT because it was a really tedious task).
Essentially, you fetch the generated openapi schema from ninja api, and you make any form field or query parameter use style: form
and explode: true
.
Here's how to apply it:
DocsBase
to render your template and use it in the NinjaAPI
:
from ninja.openapi.docs import DocsBase
class CustomSwagger(DocsBase): def render_page(self, request, api): return render(request, "swagger.html")
api = NinjaAPI(title="My API", docs=CustomSwagger())
2. You paste the following in your template `swagger.html`:
```html
<!DOCTYPE html>
<html>
<head>
<link
type="text/css"
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css"
/>
<link rel="shortcut icon" href="/media/logo.png" />
<title>My API</title>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script>
function transformOpenAPI(openApiObject) {
// Iterate through paths in the OpenAPI object
for (const path in openApiObject.paths) {
for (const method in openApiObject.paths[path]) {
const operation = openApiObject.paths[path][method];
// Transform query parameters for GET requests
if (method.toLowerCase() === "get" && operation.parameters) {
operation.parameters.forEach((param) => {
if (
param.in === "query" &&
param.schema &&
param.schema.type === "array"
) {
param.style = "form";
param.explode = true;
}
});
}
// Transform body for application/x-www-form-urlencoded
if (operation.requestBody) {
const content = operation.requestBody.content;
// Check for application/x-www-form-urlencoded
if (content["application/x-www-form-urlencoded"]) {
const formEncoding =
content["application/x-www-form-urlencoded"];
// Assuming the schema is an object with properties
if (
formEncoding.schema.type === "object" &&
formEncoding.schema.properties
) {
Object.keys(formEncoding.schema.properties).forEach(
(prop) => {
const property = formEncoding.schema.properties[prop];
if (property.type === "array") {
// Set encoding for array properties
formEncoding.encoding = formEncoding.encoding || {};
formEncoding.encoding[prop] = {
style: "form",
explode: true,
};
}
}
);
}
}
}
}
}
return openApiObject;
}
(async () => {
const r = await fetch("/api/openapi.json");
const openapi = await r.json();
transformOpenAPI(openapi);
const ui = SwaggerUIBundle({
layout: "BaseLayout",
deepLinking: true,
spec: openapi,
dom_id: "#swagger-ui",
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset,
],
});
})();
</script>
</body>
</html>
Greetings. There's been an issue to the problem I am referring to, which was closed for no reason to my understanding.
Essentially, when you define a
Schema
with aList[str]
field the openapi generated documentation is not in sync with what the schema excepts.The schema excepts a repeated value (e.g names=John&names=Jane) or through
JavaScript
code:But the openapi docs send a single comma separated string resulting to an array with a single item containing that string (e.g
["John, Jane"]
.The documentation is supposed to work out of the box. User code checking for commas to fix that library issue shouldn't be acceptable (what if the separated string contained a comma itself?).