Closed
Description
I’ve noticed that removing an optional field from a response is flagged as a breaking change.
Old OpenAPI document
{
"openapi": "3.0.0",
"info": {
"title": "API to manipulate a counter",
"version": "1.0.0"
},
"paths": {
"/counter": {
"get": {
"responses": {
"200": {
"description": "The counter current value",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Counter"
}
}
}
},
"400": {
"description": "Client error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
},
"500": {
"description": "Server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
}
}
},
"post": {
"responses": {
"200": {
"description": "The counter current value",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Counter"
}
}
}
},
"400": {
"description": "Client error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
},
"500": {
"description": "Server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Operation"
}
}
},
"description": "The operation to apply to the counter"
}
}
}
},
"components": {
"schemas": {
"counter.Operation.Set": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Set"
],
"example": "Set"
},
"value": {
"type": "integer",
"format": "int32"
}
},
"required": [
"type",
"value"
]
},
"counter.Counter": {
"type": "object",
"properties": {
"value": {
"type": "integer",
"format": "int32"
},
"timestamp": {
"type": "string",
"format": "date-time"
}
},
"required": [
"value"
]
},
"counter.Operation": {
"oneOf": [
{
"$ref": "#/components/schemas/counter.Operation.Add"
},
{
"$ref": "#/components/schemas/counter.Operation.Set"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"Add": "#/components/schemas/counter.Operation.Add",
"Set": "#/components/schemas/counter.Operation.Set"
}
}
},
"counter.Operation.Add": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Add"
],
"example": "Add"
},
"delta": {
"type": "integer",
"format": "int32"
}
},
"required": [
"type",
"delta"
]
},
"endpoints.Errors": {
"type": "array",
"items": {
"type": "string"
}
}
},
"securitySchemes": {}
}
}
Note the presence of the optional field timestamp
in the counter.Counter
component.
New OpenAPI document
{
"openapi": "3.0.0",
"info": {
"title": "API to manipulate a counter",
"version": "1.0.0"
},
"paths": {
"/counter": {
"get": {
"responses": {
"200": {
"description": "The counter current value",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Counter"
}
}
}
},
"400": {
"description": "Client error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
},
"500": {
"description": "Server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
}
}
},
"post": {
"responses": {
"200": {
"description": "The counter current value",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Counter"
}
}
}
},
"400": {
"description": "Client error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
},
"500": {
"description": "Server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/endpoints.Errors"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/counter.Operation"
}
}
},
"description": "The operation to apply to the counter"
}
}
}
},
"components": {
"schemas": {
"counter.Operation.Set": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Set"
],
"example": "Set"
},
"value": {
"type": "integer",
"format": "int32"
}
},
"required": [
"type",
"value"
]
},
"counter.Counter": {
"type": "object",
"properties": {
"value": {
"type": "integer",
"format": "int32"
}
},
"required": [
"value"
]
},
"counter.Operation": {
"oneOf": [
{
"$ref": "#/components/schemas/counter.Operation.Add"
},
{
"$ref": "#/components/schemas/counter.Operation.Set"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"Add": "#/components/schemas/counter.Operation.Add",
"Set": "#/components/schemas/counter.Operation.Set"
}
}
},
"counter.Operation.Add": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Add"
],
"example": "Add"
},
"delta": {
"type": "integer",
"format": "int32"
}
},
"required": [
"type",
"delta"
]
},
"endpoints.Errors": {
"type": "array",
"items": {
"type": "string"
}
}
},
"securitySchemes": {}
}
}
Note that the field timestamp
is absent from the counter.Counter
component.
I expect such a change to be backward compatible: clients already know how to deal with the absence of the field timestamp
since this one was optional in the first place.