xsdata icon indicating copy to clipboard operation
xsdata copied to clipboard

xsdata and Swagger 2.0 schema

Open leonardopsantos opened this issue 7 months ago • 2 comments

Sorry for the neophyte question, but I'm getting my feet wet on REST APIs just now. I've been extremelly happy using xsdata to generate bindings for IEEE IPXACT 1685-2014 data. Now I want to use it to create Python bindings for the TeamCity REST API. My problem is actually finding the schema files for the data.

I've tried pulling the data from the /app/rest/builds endpoint in XML and JSON:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <builds count="100" href="/app/rest/builds" nextHref="/app/rest/builds?locator=count:100,start:100">
        <build id="2110255" buildTypeId="Software_..." number="31726" status="SUCCESS" state="finished" branchName="refs/heads/main" defaultBranch="true" href="/app/rest/builds/id:2110255" webUrl="https://teamcity.example.com/buildConfiguration/Software_.../2110255">
            ...
        </build>
    </builds>
{
    "count":100,
    "href":"/app/rest/builds",
    "nextHref":"/app/rest/builds?locator=count:100,start:100",
    "build":[
        {
            "id":2109979,
            "buildTypeId":"Software_...",
            "number":"557",
            "status":"SUCCESS",
            "state":"finished",
            "branchName":"refs/heads/main",
            "defaultBranch":true,
            "href":"/app/rest/builds/id:2109979",
            "webUrl":"https://teamcity.example.com/buildConfiguration/Software_.../2109979",
            "finishOnAgentDate":"20250522T154005-0400"
        },
        ...
    ]
}

There's no schema reference in either format. I tried using the Swagger endpoing (dully marked as deprecated) from teamcity-rest-api

curl --header "Authorization: Bearer <token>" --header "Accept: application/json" https://teamcity.untetherai.com/app/rest/swagger.json -o teamcity.json

Which gave me this data:

{
    "swagger":"2.0",
    "info": {
        "version":"2018.1 (current)",
        "title":"TeamCity REST API"},
        "host":"teamcity.example.com",
        "tags":[
            {"name":"Agent"},
            {"name":"AgentPool"},
            {"name":"AgentType"},
            ...

I then pointed xsdata to it:

xsdata generate --package lib.xsdata_generated ./teamcity.json

Cool! I took a peek at the generated bindings:

@dataclass
class AppRestBuilds:
    class Meta:
        name = "/app/rest/builds"

    get: Optional[Get] = field(
        default=None,
        metadata={
            "type": "Element",
            "required": True,
        },
    )

I created a very trivial script:

from lib.xsdata_generated.xsdata_generated import AppRestBuilds
from xsdata.formats.dataclass.parsers import JsonParser

parser = JsonParser()
order = parser.parse("builds.json", AppRestBuilds)
print(order)

Which immediatelly fails with a xsdata.exceptions.ParserError: Unknown property AppRestBuilds.count error. Looking at the Swagger file:

    "/app/rest/builds": {
      "get": {
        "tags": ["Build"],
        "summary": "Get all builds.",
        "description": "",
        "operationId": "getAllBuilds",
        "produces": ["application/xml", "application/json"],
        "parameters": [
          {
            "name": "locator",
            "in": "query",
            "required": false,
            "type": "string",
            "format": "BuildLocator"
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "examples": { "application/xml": "", "application/json": "" },
            "schema": { "$ref": "#/definitions/builds" }
          }
        }
      }
    }

And

    "builds": {
      "type": "object",
      "properties": {
        "count": {
          "type": "integer",
          "format": "int32",
          "example": 12,
          "xml": { "attribute": true },
          "description": "The current number of Build objects in this list.",
          "x-defined-in-base": true
        },
        "href": {
          "type": "string",
          "example": "/app/rest/builds?locator=buildType:Project_Config&fields=count,href",
          "xml": { "attribute": true },
          "description": "The relative link (without the server URL) used to retrieve this object.",
          "x-defined-in-base": true
        },
        "nextHref": {
          "type": "string",
          "example": "/app/rest/builds?locator=count:200,start:250,state:finished",
          "xml": { "attribute": true },
          "description": "If the list of returned entities exceeds the request `count` value, TeamCity splits it into multiple batches. This property returns the endpoint that allows you to obtain the next batch.",
          "x-defined-in-base": true
        },
        "prevHref": {
          "type": "string",
          "example": "/app/rest/builds?locator=count:50,start:0,state:finished",
          "xml": { "attribute": true },
          "description": "If the list of returned entities exceeds the request `count` value, TeamCity splits it into multiple batches. This property returns the endpoint that allows you to obtain the previous batch.",
          "x-defined-in-base": true
        },
        "build": {
          "type": "array",
          "description": "The list of builds owned by this collection that satisfy the given locator.",
          "items": {
            "xml": { "name": "build" },
            "$ref": "#/definitions/build"
          },
          "x-is-first-container-var": true
        }
      },
      "xml": { "name": "builds" },
      "description": "Represents a paginated list of Build entities.",
      "x-object-type": "PaginatedEntity",
      "x-subpackage": ".build.",
      "x-is-data": true,
      "x-is-list": true,
      "x-is-paginated": true,
      "x-base-entity": "Build"
    },

So, count is clearly there. Is there any configuration option I should be using?

I created a stackoverflow post in case someone can point me to a schema file.

Thanks!!

leonardopsantos avatar May 22 '25 20:05 leonardopsantos

xsdata doesn't support generating models from swagger, just raw json documents

tefra avatar Jun 05 '25 02:06 tefra

OK. Even if the JSON documents are schemas?

leonardopsantos avatar Jun 05 '25 19:06 leonardopsantos