Skip to content

# Response renderers

The most common response type for a REST API is usually JSON. Django Ninja also has support for defining your own custom renderers, which gives you the flexibility to design your own media types.

## Create a renderer

To create your own renderer, you need to inherit `ninja.renderers.BaseRenderer` and override the `render` method. Then you can pass an instance of your class to `NinjaAPI` as the `renderer` argument:

    from ninja import NinjaAPI
    from ninja.renderers import BaseRenderer

    class MyRenderer(BaseRenderer):
        media_type = "text/plain"

        def render(self, request, data, *, response_status):
            return ... # your serialization here

    api = NinjaAPI(renderer=MyRenderer())

The `render` method takes the following arguments:

- request -> HttpRequest object
- data -> object that needs to be serialized
- response_status as an `int` -> the HTTP status code that will be returned to the client

You need also define the `media_type` attribute on the class to set the content-type header for the response.

## ORJSON renderer example:

orjson is a fast, accurate JSON library for Python. It benchmarks as the fastest Python library for JSON and is more accurate than the standard `json` library or other third-party libraries. It also serializes dataclass, datetime, numpy, and UUID instances natively.

Here's an example renderer class that uses `orjson`:

    import orjson
    from ninja import NinjaAPI
    from ninja.renderers import BaseRenderer

    class ORJSONRenderer(BaseRenderer):
        media_type = "application/json"

        def render(self, request, data, *, response_status):
            return orjson.dumps(data)

    api = NinjaAPI(renderer=ORJSONRenderer())

## XML renderer example:

This is how you create a renderer that outputs all responses as XML:

    from io import StringIO
    from django.utils.encoding import force_str
    from django.utils.xmlutils import SimplerXMLGenerator
    from ninja import NinjaAPI
    from ninja.renderers import BaseRenderer

    class XMLRenderer(BaseRenderer):
        media_type = "text/xml"

        def render(self, request, data, *, response_status):
            stream = StringIO()
            xml = SimplerXMLGenerator(stream, "utf-8")
            xml.startDocument()
            xml.startElement("data", {})
            self._to_xml(xml, data)
            xml.endElement("data")
            xml.endDocument()
            return stream.getvalue()

        def _to_xml(self, xml, data):
            if isinstance(data, (list, tuple)):
                for item in data:
                    xml.startElement("item", {})
                    self._to_xml(xml, item)
                    xml.endElement("item")

            elif isinstance(data, dict):
                for key, value in data.items():
                    xml.startElement(key, {})
                    self._to_xml(xml, value)
                    xml.endElement(key)

            elif data is None:
                # Don't output any value
                pass

            else:
                xml.characters(force_str(data))

    api = NinjaAPI(renderer=XMLRenderer())

(Copyright note: this code is basically copied from DRF-xml)