|
| 1 | +#Esquemas OpenAPI Separados para Entrada e Saída ou Não |
| 2 | + |
| 3 | +Ao usar**Pydantic v2**, o OpenAPI gerado é um pouco mais exato e**correto** do que antes. 😎 |
| 4 | + |
| 5 | +Inclusive, em alguns casos, ele terá até**dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saída, dependendo se eles possuem**valores padrão**. |
| 6 | + |
| 7 | +Vamos ver como isso funciona e como alterar se for necessário. |
| 8 | + |
| 9 | +##Modelos Pydantic para Entrada e Saída |
| 10 | + |
| 11 | +Digamos que você tenha um modelo Pydantic com valores padrão, como este: |
| 12 | + |
| 13 | +//// tab | Python 3.10+ |
| 14 | + |
| 15 | +```Python hl_lines="7" |
| 16 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!} |
| 17 | + |
| 18 | +# Code below omitted 👇 |
| 19 | +``` |
| 20 | + |
| 21 | +<details> |
| 22 | +<summary>👀 Visualização completa do arquivo</summary> |
| 23 | + |
| 24 | +```Python |
| 25 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
| 26 | +``` |
| 27 | + |
| 28 | +</details> |
| 29 | + |
| 30 | +//// |
| 31 | + |
| 32 | +//// tab | Python 3.9+ |
| 33 | + |
| 34 | +```Python hl_lines="9" |
| 35 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!} |
| 36 | + |
| 37 | +# Code below omitted 👇 |
| 38 | +``` |
| 39 | + |
| 40 | +<details> |
| 41 | +<summary>👀 Visualização completa do arquivo</summary> |
| 42 | + |
| 43 | +```Python |
| 44 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
| 45 | +``` |
| 46 | + |
| 47 | +</details> |
| 48 | + |
| 49 | +//// |
| 50 | + |
| 51 | +//// tab | Python 3.8+ |
| 52 | + |
| 53 | +```Python hl_lines="9" |
| 54 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!} |
| 55 | + |
| 56 | +# Code below omitted 👇 |
| 57 | +``` |
| 58 | + |
| 59 | +<details> |
| 60 | +<summary>👀 Visualização completa do arquivo</summary> |
| 61 | + |
| 62 | +```Python |
| 63 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
| 64 | +``` |
| 65 | + |
| 66 | +</details> |
| 67 | + |
| 68 | +//// |
| 69 | + |
| 70 | +###Modelo para Entrada |
| 71 | + |
| 72 | +Se você usar esse modelo como entrada, como aqui: |
| 73 | + |
| 74 | +//// tab | Python 3.10+ |
| 75 | + |
| 76 | +```Python hl_lines="14" |
| 77 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!} |
| 78 | + |
| 79 | +# Code below omitted 👇 |
| 80 | +``` |
| 81 | + |
| 82 | +<details> |
| 83 | +<summary>👀 Visualização completa do arquivo</summary> |
| 84 | + |
| 85 | +```Python |
| 86 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
| 87 | +``` |
| 88 | + |
| 89 | +</details> |
| 90 | + |
| 91 | +//// |
| 92 | + |
| 93 | +//// tab | Python 3.9+ |
| 94 | + |
| 95 | +```Python hl_lines="16" |
| 96 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!} |
| 97 | + |
| 98 | +# Code below omitted 👇 |
| 99 | +``` |
| 100 | + |
| 101 | +<details> |
| 102 | +<summary>👀 Visualização completa do arquivo</summary> |
| 103 | + |
| 104 | +```Python |
| 105 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
| 106 | +``` |
| 107 | + |
| 108 | +</details> |
| 109 | + |
| 110 | +//// |
| 111 | + |
| 112 | +//// tab | Python 3.8+ |
| 113 | + |
| 114 | +```Python hl_lines="16" |
| 115 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!} |
| 116 | + |
| 117 | +# Code below omitted 👇 |
| 118 | +``` |
| 119 | + |
| 120 | +<details> |
| 121 | +<summary>👀 Visualização completa do arquivo</summary> |
| 122 | + |
| 123 | +```Python |
| 124 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
| 125 | +``` |
| 126 | + |
| 127 | +</details> |
| 128 | + |
| 129 | +//// |
| 130 | + |
| 131 | +... então o campo`description` não será obrigatório. Porque ele tem um valor padrão de`None`. |
| 132 | + |
| 133 | +###Modelo de Entrada na Documentação |
| 134 | + |
| 135 | +Você pode confirmar que na documentação, o campo`description` não tem um**asterisco vermelho**, não é marcado como obrigatório: |
| 136 | + |
| 137 | +<divclass="screenshot"> |
| 138 | +<imgsrc="/img/tutorial/separate-openapi-schemas/image01.png"> |
| 139 | +</div> |
| 140 | + |
| 141 | +###Modelo para Saída |
| 142 | + |
| 143 | +Mas se você usar o mesmo modelo como saída, como aqui: |
| 144 | + |
| 145 | +//// tab | Python 3.10+ |
| 146 | + |
| 147 | +```Python hl_lines="19" |
| 148 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
| 149 | +``` |
| 150 | + |
| 151 | +//// |
| 152 | + |
| 153 | +//// tab | Python 3.9+ |
| 154 | + |
| 155 | +```Python hl_lines="21" |
| 156 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
| 157 | +``` |
| 158 | + |
| 159 | +//// |
| 160 | + |
| 161 | +//// tab | Python 3.8+ |
| 162 | + |
| 163 | +```Python hl_lines="21" |
| 164 | +{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
| 165 | +``` |
| 166 | + |
| 167 | +//// |
| 168 | + |
| 169 | +... então, como`description` tem um valor padrão, se você**não retornar nada** para esse campo, ele ainda terá o**valor padrão**. |
| 170 | + |
| 171 | +###Modelo para Dados de Resposta de Saída |
| 172 | + |
| 173 | +Se você interagir com a documentação e verificar a resposta, mesmo que o código não tenha adicionado nada em um dos campos`description`, a resposta JSON contém o valor padrão (`null`): |
| 174 | + |
| 175 | +<divclass="screenshot"> |
| 176 | +<imgsrc="/img/tutorial/separate-openapi-schemas/image02.png"> |
| 177 | +</div> |
| 178 | + |
| 179 | +Isso significa que ele**sempre terá um valor**, só que às vezes o valor pode ser`None` (ou`null` em termos de JSON). |
| 180 | + |
| 181 | +Isso quer dizer que, os clientes que usam sua API não precisam verificar se o valor existe ou não, eles podem**assumir que o campo sempre estará lá**, mas que em alguns casos terá o valor padrão de`None`. |
| 182 | + |
| 183 | +A maneira de descrever isso no OpenAPI é marcar esse campo como**obrigatório**, porque ele sempre estará lá. |
| 184 | + |
| 185 | +Por causa disso, o JSON Schema para um modelo pode ser diferente dependendo se ele é usado para**entrada ou saída**: |
| 186 | + |
| 187 | +* para**entrada**, o`description`**não será obrigatório** |
| 188 | +* para**saída**, ele será**obrigatório** (e possivelmente`None`, ou em termos de JSON,`null`) |
| 189 | + |
| 190 | +###Modelo para Saída na Documentação |
| 191 | + |
| 192 | +Você pode verificar o modelo de saída na documentação também, ambos`name` e`description` são marcados como**obrigatórios** com um**asterisco vermelho**: |
| 193 | + |
| 194 | +<divclass="screenshot"> |
| 195 | +<imgsrc="/img/tutorial/separate-openapi-schemas/image03.png"> |
| 196 | +</div> |
| 197 | + |
| 198 | +###Modelo para Entrada e Saída na Documentação |
| 199 | + |
| 200 | +E se você verificar todos os Schemas disponíveis (JSON Schemas) no OpenAPI, verá que há dois, um`Item-Input` e um`Item-Output`. |
| 201 | + |
| 202 | +Para`Item-Input`,`description`**não é obrigatório**, não tem um asterisco vermelho. |
| 203 | + |
| 204 | +Mas para`Item-Output`,`description`**é obrigatório**, tem um asterisco vermelho. |
| 205 | + |
| 206 | +<divclass="screenshot"> |
| 207 | +<imgsrc="/img/tutorial/separate-openapi-schemas/image04.png"> |
| 208 | +</div> |
| 209 | + |
| 210 | +Com esse recurso do**Pydantic v2**, sua documentação da API fica mais**precisa**, e se você tiver clientes e SDKs gerados automaticamente, eles serão mais precisos também, proporcionando uma melhor**experiência para desenvolvedores** e consistência. 🎉 |
| 211 | + |
| 212 | +##Não Separe Schemas |
| 213 | + |
| 214 | +Agora, há alguns casos em que você pode querer ter o**mesmo esquema para entrada e saída**. |
| 215 | + |
| 216 | +Provavelmente, o principal caso de uso para isso é se você já tem algum código de cliente/SDK gerado automaticamente e não quer atualizar todo o código de cliente/SDK gerado ainda, você provavelmente vai querer fazer isso em algum momento, mas talvez não agora. |
| 217 | + |
| 218 | +Nesse caso, você pode desativar esse recurso no**FastAPI**, com o parâmetro`separate_input_output_schemas=False`. |
| 219 | + |
| 220 | +/// info | Informação |
| 221 | + |
| 222 | +O suporte para`separate_input_output_schemas` foi adicionado no FastAPI`0.102.0`. 🤓 |
| 223 | + |
| 224 | +/// |
| 225 | + |
| 226 | +//// tab | Python 3.10+ |
| 227 | + |
| 228 | +```Python hl_lines="10" |
| 229 | +{!> ../../docs_src/separate_openapi_schemas/tutorial002_py310.py!} |
| 230 | +``` |
| 231 | + |
| 232 | +//// |
| 233 | + |
| 234 | +//// tab | Python 3.9+ |
| 235 | + |
| 236 | +```Python hl_lines="12" |
| 237 | +{!> ../../docs_src/separate_openapi_schemas/tutorial002_py39.py!} |
| 238 | +``` |
| 239 | + |
| 240 | +//// |
| 241 | + |
| 242 | +//// tab | Python 3.8+ |
| 243 | + |
| 244 | +```Python hl_lines="12" |
| 245 | +{!> ../../docs_src/separate_openapi_schemas/tutorial002.py!} |
| 246 | +``` |
| 247 | + |
| 248 | +//// |
| 249 | + |
| 250 | +###Mesmo Esquema para Modelos de Entrada e Saída na Documentação |
| 251 | + |
| 252 | +E agora haverá um único esquema para entrada e saída para o modelo, apenas`Item`, e`description`**não será obrigatório**: |
| 253 | + |
| 254 | +<divclass="screenshot"> |
| 255 | +<imgsrc="/img/tutorial/separate-openapi-schemas/image05.png"> |
| 256 | +</div> |
| 257 | + |
| 258 | +Esse é o mesmo comportamento do Pydantic v1. 🤓 |