Search code examples
pythonaiohttppython-dataclasses

dataclass with aiohttp - convert invalid values to int, float or str


I'm trying to use a dataclass object to pass to the params of the aiohttp get request, but aiohttp only accept float, int or str as type in the params since it's the job of the user to handle those cases.

Let's say I want the following conversions:

    True  -> 'True'
    False -> 'False'
    None  -> ''

How can I achieve that conversion without manually doing the conversion before the request?

Here an example script that explain what I want to achieve:

import asyncio
import aiohttp
from typing import Optional
from dataclasses import dataclass
from dataclasses_json import dataclass_json

@dataclass
class Params:
    a: bool
    b: str
    c: Optional[float] = None


async def main():

    params = Params(
        a = True,
        b = 'b',
    )

    async with aiohttp.ClientSession() as session:
        async with session.get('http://www.example.com', params=convert(params))) as r:
            print(await r.text())

asyncio.run(main())

Solution

  • By using the fields method from dataclass, I can iterate throught the dataclass' fields and do the conversion according to the value:

    from dataclasses import fields
    
    def convert(dc: dataclass, mapping=None):
    
        if mapping is None:
            mapping = {
                None: '',
                True: str(True),
                False: str(False),
            }
    
        def _convert(value):
            if value in mapping:
                return mapping[value]
            return value
    
        return { field.name: _convert(getattr(dc, field.name)) for field in fields(dc) }
    

    Note that this doesn't work with nested dataclasses, but aiohttp doesn't handle them either.