Closed skinkie closed 1 year ago
Thanks for your interest in this project and your detailed error description. It helped a lot to figure out what's going on.
Based on the code provided there is a problem with the medadata of Ojp.version
. Fastapi
converts any dataclass
into a pydantic
model. Thereby, any metadata field gets passed to the pydantic
field. However, the keyword required
is reserved for these fields and causes an error if available in a dataclass
. Remove the keyword required
and it should work.
Nevertheless, the classes Ojprequest
, Ojpresponse
, and Extensions2
might cause errors too. Since I do not have any information about these classes I can only tell that the following code without the required
keyword works a least. Please let me know if this helps you out.
from dataclasses import dataclass, field
from fastapi import FastAPI
from fastapi_xml import add_openapi_extension
from fastapi_xml import NonJsonRoute
from fastapi_xml import XmlAppResponse
from fastapi_xml import XmlBody
from typing import Optional
@dataclass
class Ojprequest:
message: str = field(metadata={"example": "Foo","name": "Message", "type": "Element"})
@dataclass
class Ojpresponse:
message: str = field(metadata={"example": "Foo","name": "Message", "type": "Element"})
@dataclass
class Extensions2:
message: str = field(metadata={"example": "Foo","name": "Message", "type": "Element"})
@dataclass
class Ojp:
"""
Root element for OJP messages based on SIRI message exchange protocol.
"""
class Meta:
name = "OJP"
namespace = "http://www.siri.org.uk/siri"
ojprequest: Optional[Ojprequest] = field(
default=None,
metadata={
"name": "OJPRequest",
"type": "Element",
}
)
ojpresponse: Optional[Ojpresponse] = field(
default=None,
metadata={
"name": "OJPResponse",
"type": "Element",
}
)
extensions: Optional[Extensions2] = field(
default=None,
metadata={
"name": "Extensions",
"type": "Element",
}
)
version: str = field(
init=False,
default="1.1-dev",
metadata={
"type": "Attribute"
}
)
@dataclass
class HelloWorld:
message: str = field(metadata={"example": "Foo","name": "Message", "type": "Element"})
app = FastAPI(title="FastAPI::XML", default_response_class=XmlAppResponse)
app.router.route_class = NonJsonRoute
add_openapi_extension(app)
@app.post("/echo", response_model=Ojp, tags=["Example"])
def echo(x: HelloWorld = XmlBody()) -> HelloWorld:
x.message += " For ever!"
return x
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
I rather not change the output of the generated code. That would circumvent the idea of full integration. The full schema can be found below.
Understandable. Nevertheless, the given exception cannot be solved within the scope of this project without modifying the generated code. This is an error caused outside of fastapi-xml; Either by pyndatic while converting the model, or by xsdata while generating it. Consequently, I consider this issue as closed.
The point is that an xsd with a minOccurs will fail. I consider that not a general solution, now I have 'resolved' it unelegantly with the Response and Request, but there must be a way to make this more generic.
https://github.com/openTdataCH/ojp-nova/blob/master/server.py#L21
I just by accident found your project, and I would consider the approach to be both interesting and useful. As a xsData user I am very interested in this bridge. You write that FastAPI-XML supports xsData classes "Together, fastapi handles xml data structures using dataclasses generated by xsdata."
I have created ``xsdata generate -p ojp -ss clusters --compound-fields /home/skinkie/Sources/OJP/OJP.xsd``` I have modified the "HelloWorld" example with my root element "Ojp". Still I end up with the error below. What would create the full end to end solution to support below?
Your HelloWorld looks like:
While the generated Ojp interface looks like below.