Skip to content

Support for list messages #25

Open
@Antoine-dh

Description

@Antoine-dh

I wanted to return a json message that is directly a list at its root element
For context, my use case is for making a REST client that returns the response body as a IOP message that can be deserialized into a dataclass.
This works well for singular objects, however I have some troubles when the json response's root element is a list, because of course:

The message must be an instance of a class that is a subclass of Message or IRISObject %Persistent class. -

To work around this issue, I tried to make a list/message hybrid class such as:

@dataclass(init=False)
class PetList(list[Pet], Message):
    pass

This works well as the list is correctly serialized into a IOP message, until the sender tries to deserialize it

Traceback (most recent call last):
File "/irisdev/app/src/python/demo/bs.py", line 31, in on_process_input
response: PetList = self.send_request_sync('PetstoreOperation', RESTRequest.create('find_pets_by_status'))
File "/home/irisowner/.local/lib/python3.10/site-packages/iop/_business_host.py", line 70, in dispatch_serializer
return fonction(self, *serialized, **param2)
File "/home/irisowner/.local/lib/python3.10/site-packages/iop/_business_host.py", line 84, in dispatch_deserializer
return self._dispatch_deserializer(fonction(self,*params, **param2))
File "/home/irisowner/.local/lib/python3.10/site-packages/iop/_business_host.py", line 302, in _dispatch_deserializer
return self._deserialize_message(serial)
File "/home/irisowner/.local/lib/python3.10/site-packages/iop/_business_host.py", line 340, in _deserialize_message
msg = self._dataclass_from_dict(msg,jdict)
File "/home/irisowner/.local/lib/python3.10/site-packages/iop/_business_host.py", line 358, in _dataclass_from_dict
for key,val in dikt.items():
AttributeError: 'list' object has no attribute 'items'

So I thought I could just alternatively wrap every response into a generic class such as:

from iop import Message
from dataclasses import dataclass
from pydantic import BaseModel
from typing import TypeVar, Generic, Optional

_T = TypeVar('T')

@dataclass(init=False)
class RESTResponse(BaseModel, Generic[_T], Message):
    data: Optional[_T] = None

And this almost worked, but unfortunately the generic type is interpreted as a dict and is not deserialized correctly.
So in order to make this work I would have to define a wrapper class for every different list type my API returns which is not ideal.

Maybe a solution would be for IOP to implement a ListMessage class, or detect if the response class is a list and deserialize objects individually.

Let me know what you think about this,
Thank you

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions