Is your feature request related to a problem? Please describe.
Jane can not process usages of oneOf
which often used in OpenAPI schemas
Describe the solution you'd like
Right now I do not have fully-scale solution for support of oneOf
. Saying full-scale solution I mean at least two aspects:
- building an object model (classes) against OpenAPI specs
- converting the data being transferred during the usage of the API via the SDK
First I'd like to discuss what we want to receive in PHP code when we use oneOf
i.e what classes should be built from schemas with oneOf
First of all I think we must strictly distinguish the contexts of oneOf
keywords usage. There can be two options:
oneOf
applied to the entity which has its own name and therefore can be explicitly converted to some class in object oriented programming languages like PHP
{
"Entity": {
"type": "object",
"oneOf": [
......
]
}
}
oneOf
applied to properties
{
"Entity": {
"type": "object",
"properties": {
"theProperty": {
"type": "object",
"oneOf": [
.......
]
}
}
}
In terms of programming languages which support types, oneOf
naturally corresponds with the union
types and the best option is - to convert all usages of oneOf
into unions. In PHP it’s possible to use syntax of union in argument and property declarations, but it’s not possible to declare custom type as a union of types, so some tricks will be required to process such cases
OneOf for Entity
OneOf custom types
In PHP it’s not possible to declare custom type as a union of types and where possible we can do some tricks replacing union with inheritance
Schema Example:
{
"Entity": {
"type": "object",
"title": "Entity which can be TypeOne or TypeTwo",
"oneOf": [
{
"$ref": "#/components/schemas/TypeOne"
},
{
"$ref": "#/components/schemas/TypeTwo"
}
]
},
"TypeOne": {
"type": "object",
"title": "TypeOne",
"properties": {
"typeOneProperty": {
"type": "string"
}
}
},
"TypeTwo": {
"type": "object",
"title": "TypeTwo",
"properties": {
"typeTwoProperty": {
"type": "string"
}
}
}
}
PHP Code:
class Entity {
}
class TypeOne extends Entity {
/**
* @var string
*/
private $typeOneProperty;
}
class TypeTwo extends Entity {
/**
* @var string
*/
private $typeTwoProperty;
}
OneOf built-in types
But it’s also not possible to declare that your entity is one of primitive types.
Schema Example:
"components": {
"schemas": {
"Entity": {
"type": "object",
"title": "An Entity which can be an integer or a string",
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
}
]
}
}
}
PHP Code:
PHP does not allow declare classes which can be union of several types, we can not declare that some class is a parent for integer and string. I'm afraid no way to process such cases for in PHP-clients
OneOf for property
It’s possible to use syntax of union in argument and property declarations
OneOf built-in types
Schema Example:
{
"Entity": {
"type": "object",
"title": "Entity which can be TypeOne or TypeTwo",
"properties": {
"theProperty": {
"type": "object",
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
}
]
}
}
}
}
PHP Code:
class Entity {
/**
\* @var int|string
*/
private $theProperty;
/**
* @return int|string
*/
public function getTheProperty()
{
return $this->theProperty;
}
/**
* @param int|string $theProperty
*/
public function setTheProperty($theProperty): void
{
$this->theProperty = $theProperty;
}
}
OneOf custom types
Schema Example:
{
"Entity": {
"type": "object",
"title": "Entity which can be TypeOne or TypeTwo",
"properties": {
"theProperty": {
"type": "object",
"oneOf": [
{
"$ref": "#/components/schemas/TypeOne"
},
{
"$ref": "#/components/schemas/TypeTwo"
}
]
}
}
},
"TypeOne": {
"type": "object",
"title": "TypeOne",
"properties": {
"typeOneProperty": {
"type": "string"
}
}
},
"TypeTwo": {
"type": "object",
"title": "TypeTwo",
"properties": {
"typeTwoProperty": {
"type": "string"
}
}
}
}
PHP Code:
class Entity {
/**
* @var TypeOne|TypeTwo
*/
private $theProperty;
/**
* @return TypeOne|TypeTwo
*/
public function getTheProperty()
{
return $this->theProperty;
}
/**
* @param TypeOne|TypeTwo $theProperty
*/
public function setTheProperty($theProperty): void
{
$this->theProperty = $theProperty;
}
}
class TypeOne {
/**
* @var string
*/
private $typeOneProperty;
}
class TypeTwo {
/**
* @var string
*/
private $typeTwoProperty;
}
Conclusion
If we agree about expected result in terms of PHP classes, I could continue working on how this conversion can be achieved in terms of serialization. Looking forward for your reply. Cheers
enhancement