datamodel-code-generator icon indicating copy to clipboard operation
datamodel-code-generator copied to clipboard

Generate schemas from paths.

Open DavidMeu opened this issue 4 years ago • 14 comments

Want to be able to create models from paths schemas. Is there any way to nest and generate also from that level? Example for that snippet:

paths:
  /users/{id}:
    get:
      tags:
        - Users
      summary: Gets a user by ID.
      description: >
        A detailed description of the operation.
        Use markdown for rich text representation,
        such as **bold**, *italic*, and [links](https://swagger.io).
      operationId: getUserById
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int64

model name getUserById with matching params.

DavidMeu avatar May 19 '21 08:05 DavidMeu

@DavidMeu Thank you for creating this issue. I feel that this idea is good. I will add the feature as a CLI option.

koxudaxi avatar May 20 '21 14:05 koxudaxi

@DavidMeu I'm working on the issue.

model name getUserById with matching params.

Did you expect to create a root model like this?

class GetUserById(BaseModel):
   __root__: int

fastapi-code-generator can create a model from content in paths.

koxudaxi avatar Jun 07 '21 17:06 koxudaxi

@koxudaxi No just like the native way. for:

  schemas:
    ObjSummary:
      type: object
      properties:
        id:
          type: string
          description: 'A unique id'
          example: 5e7c6cf54b832e0018f191ad
        source:
          type: string
          description: The name of system
          example: Company

creates:

class ObjSummary(BaseModel):
   id: str
   source: str

And for the paths utility: Another example: for:

paths:
  /objects:
    post:
      operationId: createObj
      summary: Creates a new obj
      description: description
      tags:
        - objects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: The name of the obj
                  example: example
                source:
                  type: string
                  description: 'description.'
                  example: example

creates:

class CreateObj(BaseModel):
   name: str
   source: str

fastapi-code-generator can create a model from content in paths.

Right but it is not from OpenAPI files (yamls)

DavidMeu avatar Jun 08 '21 07:06 DavidMeu

@DavidMeu Thank you for show me examples.

Right but it is not from OpenAPI files (yamls)

What file type is the file? I have guessed the contents is OpenAPI :thinking:

I'm implementing a parser of paths that is for OpenAPI. https://github.com/koxudaxi/datamodel-code-generator/pull/438 Can not resolve the PR your problem?

koxudaxi avatar Jun 08 '21 17:06 koxudaxi

I have guessed the contents is OpenAPI

correct

I'm implementing a parser of paths that is for OpenAPI. #438

I'll check it out 10x

DavidMeu avatar Jul 21 '21 06:07 DavidMeu

@koxudaxi Is there some flag I should use? What is the exact command sample?

DavidMeu avatar Jul 21 '21 07:07 DavidMeu

Hello!

I've tried using the unreleased git version which includes #438 with an OpenAPI generated by FastAPI, and got the error Models not found in the input data, when using --openapi-scopes paths. Should I be using https://github.com/koxudaxi/fastapi-code-generator instead?

A minimal schema for reproduction

{
  "openapi": "3.0.2",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/items": {
      "get": {
        "summary": "Search Items",
        "description": "Retrieve a dialog",
        "operationId": "search_items_items_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "title": "Search Parameter",
              "type": "string"
            },
            "name": "search_parameter",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HTTPValidationError": {
        "title": "HTTPValidationError",
        "type": "object",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "Item": {
        "title": "Item",
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          }
        }
      },
      "SearchResponse": {
        "title": "SearchResponse",
        "required": [
          "items"
        ],
        "type": "object",
        "properties": {
          "items": {
            "title": "Items",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Item"
            }
          }
        }
      },
      "ValidationError": {
        "title": "ValidationError",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "type": "object",
        "properties": {
          "loc": {
            "title": "Location",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        }
      }
    }
  }
}

vogre avatar Aug 02 '21 08:08 vogre

@DavidMeu I'm sorry for my late reply. I put the example.

$ datamodel-codegen --input openapi.yaml --openapi-scopes  schemas paths --input-file-type openapi

Output

# generated by datamodel-codegen:
#   filename:  openapi.yaml
#   timestamp: 2021-08-09T18:11:18+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field


class ObjectsPostRequest(BaseModel):
    name: Optional[str] = Field(
        None, description='The name of the obj', example='example'
    )
    source: Optional[str] = Field(None, description='description.', example='example')


koxudaxi avatar Aug 09 '21 18:08 koxudaxi

@vogre I tried your example with the newest version of datamodel-code-generator Did you expect the output?

datamodel-codegen --input openapi.json --openapi-scopes schemas paths --input-file-type openapi

Output

# generated by datamodel-codegen:
#   filename:  openapi.json
#   timestamp: 2021-08-09T18:16:03+00:00

from __future__ import annotations

from typing import List, Optional

from pydantic import BaseModel, Field


class Item(BaseModel):
    name: str = Field(..., title='Name')


class SearchResponse(BaseModel):
    items: List[Item] = Field(..., title='Items')


class ValidationError(BaseModel):
    loc: List[str] = Field(..., title='Location')
    msg: str = Field(..., title='Message')
    type: str = Field(..., title='Error Type')


class HTTPValidationError(BaseModel):
    detail: Optional[List[ValidationError]] = Field(None, title='Detail')

koxudaxi avatar Aug 09 '21 18:08 koxudaxi

@koxudaxi I expected to see the schema for search_parameter, but it's missing from the output. I'm getting no difference whether I'm passing --openapi-scopes schemas or --openapi-scopes schemas paths.

vogre avatar Aug 11 '21 09:08 vogre

@vogre

I expected to see the schema for search_parameter,

Did you expect a model of this schema in your example?

        "parameters": [
          {
            "required": true,
            "schema": {
              "title": "Search Parameter",
              "type": "string"
            },
            "name": "search_parameter",
            "in": "query"
          }
        ],

This schema is string type. So, the code-generator doesn't create a model for the schema. What result do you want a result?

koxudaxi avatar Aug 12 '21 17:08 koxudaxi

@koxudaxi even when there are constraints introduced, the generator does not seem to be generating models for path/query schemas.

example:

components:
  parameters:
    PetId:
      name: petId
      in: path
      required: true
      schema:
        type: integer
        minimum: 1

referenced by:

    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - $ref: "#/components/parameters/PetId"

command used to generate the model:

datamodel-codegen --input input.yaml  --output output.py  --target-python-version 3.8 --validation --field-constraints --field-include-all-keys --input-file-type openapi --openapi-scopes schemas paths

is this the expected behavior?

ck-on-github avatar Sep 15 '21 09:09 ck-on-github

@cansukaynak

is this the expected behavior?

Yes. I heard a lot of feedback from users. And, I had known they usually don't want to generate constraints value. like this.

class PetId(BaseModel):
    __root__: int = Field(..., ge=1)

koxudaxi avatar Sep 15 '21 14:09 koxudaxi

@koxudaxi I understand why there is no model generated for path params. but for query params, OpenAPI actually allows for default, min and max. https://swagger.io/docs/specification/describing-parameters/ See "Default Parameter Values" Wouldn't it make sense to generate models for query parameters?

ck-on-github avatar Feb 09 '22 11:02 ck-on-github