Hi,
We're working on a resource operation which might return different implementations of a given interface. Let's say it's an operation returning a Pet, which can be either a Dog, or a Cat. Additionally all my Pets have a common property, "noise". I wouldn't like to go into inheritance vs composition discussion, but am rather searching for help on how to model this in the OpenApi schema, in the most correct and easiest to use way. The four alternatives that I can think of are: 1. The resource operation returns the Pet schema which can be oneOf Dog or Cat. Repeat the common property on both Dog and Cat. { "openapi": "3.0.1", "info": { "title": "notitle", "version": "1.0.0" }, "paths": { "/pets/": { "get": { "parameters": [], "responses": { "default": { "description": "default response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } } }, "components": { "schemas": { "Cat": { "type": "object", "properties": { "noise": { "type": "string" }, "catProperty": { "type": "string" } } }, "Dog": { "type": "object", "properties": { "noise": { "type": "string" }, "dogProperty": { "type": "string" } } }, "Pet": { "type": "object", "oneOf": [ { "$ref": "#/components/schemas/Dog" }, { "$ref": "#/components/schemas/Cat" } ] } } } } 2. The resource operation returns oneOf Dog or Cat. This actually makes the Pet a hidden parent, as it's not used by any operation. I'm afraid it might be hard to use in strongly typed clients, as there is no common parent for Dog and Cat. Additionally when pasted into swagger editor, this doesn't model the operation result in a nice way. { "openapi": "3.0.1", "info": { "title": "notitle", "version": "1.0.0" }, "paths": { "/pets": { "get": { "operationId": "getPet", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "string", "description": "ret", "oneOf": [ { "$ref": "#/components/schemas/Dog" }, { "$ref": "#/components/schemas/Cat" } ] } } } } } } } }, "components": { "schemas": { "Cat": { "type": "object", "properties": { "noise": { "type": "string" }, "catProperty": { "type": "string" } } }, "Dog": { "type": "object", "properties": { "noise": { "type": "string" }, "dogProperty": { "type": "string" } } } } } } 3. The rest operation returns oneOf Cat/Dog as above, which are composed of own properties and allOf properties from the Pet model. Again, I'm afraid, that without polymorphism this might be hard to use in strongly typed clients. { "openapi": "3.0.1", "info": { "title": "notitle", "version": "1.0.0" }, "paths": { "/pets": { "get": { "operationId": "getPet", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "string", "description": "ret", "oneOf": [ { "$ref": "#/components/schemas/Dog" }, { "$ref": "#/components/schemas/Cat" } ] } } } } } } } }, "components": { "schemas": { "Cat": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/Pet" }, { "properties": { "catProperty": { "type": "string" } } } ] }, "Dog": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/Pet" }, { "properties": { "catProperty": { "type": "string" } } } ] }, "Pet": { "type": "object", "properties": { "noise": { "type": "string" } } } } } } 4. A mix of polymorphism and aggregation. Here we have a common parent for Dog and Cat (the Pet model), the resource operation returns the Pet. Additionally we have extracted the common behaviour to PetBehaviour model and use allOf their properties in Cat and Dog. { "openapi": "3.0.1", "info": { "title": "notitle", "version": "1.0.0" }, "paths": { "/pets": { "get": { "operationId": "getPet", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } } }, "components": { "schemas": { "PetBehaviour": { "type": "object", "properties": { "noise": { "type": "string" } } }, "Cat": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/PetBehaviour" }, { "properties": { "catProperty": { "type": "string" } } } ] }, "Dog": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/PetBehaviour" }, { "properties": { "dogProperty": { "type": "string" } } } ] }, "Pet": { "type": "object", "oneOf": [ { "$ref": "#/components/schemas/Dog" }, { "$ref": "#/components/schemas/Cat" } ] } } } } Sorry for this long question, but I feel we're not the only ones struggling with modelling polymorphism and composition in the OpenApi. I didn't find a single example with a resource operation returning an object, which can be oneOf multiple implementations. It's always the response that defines oneOf. All of the examples seems to be syntactically correct, they do properly validate in the swagger editor. Which one in your opinion should be preferred? Can you state any of them is definitely incorrect. Best Regards, Michal -- You received this message because you are subscribed to the Google Groups "Swagger" group. To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.