-
Notifications
You must be signed in to change notification settings - Fork 10k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gRPC JSON transcoding + Microsoft.AspNetCore.OpenApi #56067
Conversation
Example of Swashbuckle output: {
"openapi": "3.0.1",
"info": {
"title": "My API",
"version": "v1"
},
"paths": {
"/v1/greeter/{name}": {
"get": {
"tags": [
"Greeter"
],
"summary": "Say hello.",
"parameters": [
{
"name": "name",
"in": "path",
"description": "Name to greet.",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloReply"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Status"
}
}
}
}
}
}
},
"/v1/greeter": {
"post": {
"tags": [
"Greeter"
],
"summary": "Sends a greeting from someone.",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloRequestFrom"
}
}
}
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloReply"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Status"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Any": {
"required": [
"@type"
],
"type": "object",
"properties": {
"@type": {
"type": "string"
}
},
"additionalProperties": {
"$ref": "#/components/schemas/Value"
}
},
"HelloReply": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Greeting message."
},
"nested": {
"$ref": "#/components/schemas/HelloReply"
}
},
"additionalProperties": false
},
"HelloRequestFrom": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet."
},
"from": {
"type": "string",
"description": "Greeting from."
}
},
"additionalProperties": false
},
"KindOneofCase": {
"enum": [
0,
1,
2,
3,
4,
5,
6
],
"type": "integer",
"format": "int32"
},
"ListValue": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Value"
},
"nullable": true,
"readOnly": true
}
},
"additionalProperties": false
},
"NullValue": {
"enum": [
0
],
"type": "integer",
"format": "int32"
},
"Status": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Any"
}
}
},
"additionalProperties": false
},
"Struct": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/Value"
},
"nullable": true,
"readOnly": true
}
},
"additionalProperties": false
},
"Value": {
"type": "object",
"properties": {
"nullValue": {
"$ref": "#/components/schemas/NullValue"
},
"hasNullValue": {
"type": "boolean",
"readOnly": true
},
"numberValue": {
"type": "number",
"format": "double"
},
"hasNumberValue": {
"type": "boolean",
"readOnly": true
},
"stringValue": {
"type": "string",
"nullable": true
},
"hasStringValue": {
"type": "boolean",
"readOnly": true
},
"boolValue": {
"type": "boolean"
},
"hasBoolValue": {
"type": "boolean",
"readOnly": true
},
"structValue": {
"$ref": "#/components/schemas/Struct"
},
"listValue": {
"$ref": "#/components/schemas/ListValue"
},
"kindCase": {
"$ref": "#/components/schemas/KindOneofCase"
}
},
"additionalProperties": false
}
}
},
"tags": [
{
"name": "Greeter",
"description": "The greeting service definition."
}
]
} |
Example of current Microsoft.AspNetCore.OpenApi: {
"openapi": "3.0.1",
"info": {
"title": "Sandbox | v1",
"version": "1.0.0"
},
"paths": {
"/v1/greeter/{name}": {
"get": {
"tags": [
"Greeter"
],
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { }
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": { }
}
}
}
}
}
},
"/v1/greeter": {
"post": {
"tags": [
"Greeter"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { }
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": { }
}
}
}
}
}
}
},
"tags": [
{
"name": "Greeter"
}
]
} Schemas for complex objects are currently empty. Also, I couldn't find an example of enabling documentaiton. |
0a019a1
to
422fb18
Compare
dbcff55
to
0650d87
Compare
Microsoft.AspNetCore.OpenApi json after changes: {
"openapi": "3.0.1",
"info": {
"title": "Sandbox | v1",
"version": "1.0.0"
},
"paths": {
"/v1/greeter/{name}": {
"get": {
"tags": [
"Greeter"
],
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": { }
}
}
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"typeUrl": {
"type": "string"
},
"value": {
"type": "array",
"items": {
"type": "string",
"format": "byte"
}
}
}
}
}
}
}
}
}
}
}
}
},
"/v1/greeter": {
"post": {
"tags": [
"Greeter"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": { }
}
}
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"typeUrl": {
"type": "string"
},
"value": {
"type": "array",
"items": {
"type": "string",
"format": "byte"
}
}
}
}
}
}
}
}
}
}
}
}
}
},
"tags": [
{
"name": "Greeter"
}
]
} Note: This is from running the sandbox project inside the gRPC solution view. Gaps I see:
|
4519fc0
to
2139eed
Compare
I rebased to latest and looked at this more.
The nested property now references something that doesn't exist. I don't know why it does this.
Also, there are duplicated definitions in the references. e.g. Every time I refresh the OpenAPI document on the server, the reference numbers increase. For example, For example, imagine there are two OpenApi docs and each have their own class called I noticed arrays are a referenced type, e.g. {
"type": "array",
"items": {
"$ref": "#/components/schemas/Value"
},
"nullable": true,
"readOnly": true
} If someone wants to view the JSON for a collection, having to look up an array reference to then look at the array's item reference makes the JSON harder to read than necessary. Swashbuckle doesn't add array/collection references. Current JSON: {
"openapi": "3.0.1",
"info": {
"title": "Sandbox | v1",
"version": "1.0.0"
},
"paths": {
"/v1/greeter/{name}": {
"get": {
"tags": [
"Greeter"
],
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloReply17"
}
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Status9"
}
}
}
}
}
}
},
"/v1/greeter": {
"post": {
"tags": [
"Greeter"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloRequestFrom9"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HelloReply17"
}
}
}
},
"default": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Status9"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"ArrayOfAny": {
"type": "array",
"nullable": true
},
"HelloReply": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply10": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply11": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply12": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply13": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply14": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply15": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply16": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply17": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply18"
}
}
},
"HelloReply18": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply2": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply3": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply4": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply5": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply6": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply7": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloReply8": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/#/properties/nested"
}
},
"nullable": true
},
"HelloReply9": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nested": {
"$ref": "#/components/schemas/HelloReply16"
}
}
},
"HelloRequestFrom": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom2": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom3": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom4": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom5": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom6": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom7": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom8": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"HelloRequestFrom9": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"from": {
"type": "string"
}
}
},
"Status": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status2": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status3": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status4": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status5": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status6": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status7": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status8": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
},
"Status9": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32",
"nullable": true
},
"message": {
"type": "string"
},
"details": {
"$ref": "#/components/schemas/ArrayOfAny"
}
}
}
}
},
"tags": [
{
"name": "Greeter"
}
]
} |
I think that's #56541. |
Paused until schema generator customization improves. |
Work in progress.
Note: I needed to make some changes to the
IApiDescriptionProvider
.Microsoft.AspNetCore.OpenApi
usesApiParameterDescription.Type
in places that Swashbuckle usedApiParameterDescription.ModelMetadata.ModelType
. I don't know if that change was intentional.