OpenAPITools / OpenAPITools/openapi-generator
[REQ][PHP] Discriminator does not actually work when using ObjectSerializer::deserialize()
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Is your feature request related to a problem? Please describe.
I don't think the current implementation of discriminator actually works as expected. Passing an array of data to ObjectSerializer::deserialize() does not instantiate the correct child class.
openapi: 3.0.3
info:
title: 'API'
version: 1.0.0
servers:
-
url: 'https://example.com'
paths:
/foo:
post:
tags:
- Bar
summary: 'Summary'
operationId: foo
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PetBaseObject'
responses:
'200':
description: 'successful operation'
components:
schemas:
PetBaseObject:
type: object
required:
- pet_type
properties:
pet_type:
type: string
discriminator:
propertyName: pet_type
mapping:
dog: '#/components/schemas/PetDog'
cat: '#/components/schemas/PetCat'
fish: '#/components/schemas/PetFish'
PetDog:
type: object
allOf:
- $ref: '#/components/schemas/PetBaseObject'
-
required:
- pet_type
properties:
pet_type:
type: string
default: dog
likes_fetch:
type: boolean
PetCat:
type: object
allOf:
- $ref: '#/components/schemas/PetBaseObject'
-
required:
- pet_type
properties:
pet_type:
type: string
default: cat
likes_catnip:
type: boolean
PetFish:
type: object
allOf:
- $ref: '#/components/schemas/PetBaseObject'
-
required:
- pet_type
properties:
pet_type:
type: string
default: fish
water_type:
type: string
<?php
require_once __DIR__ . '/vendor/autoload.php';
$pet = OpenAPI\Client\ObjectSerializer::deserialize([
'pet_type' => 'cat',
'likes_catnip' => false,
], OpenAPI\Client\Model\PetBaseObject::class);
var_dump($pet);
$ php test.php
object(OpenAPI\Client\Model\PetBaseObject)#3 (1) {
["container":protected]=>
array(1) {
["pet_type"]=>
string(13) "PetBaseObject"
}
}
Describe the solution you'd like
I would expect discriminator instantiation to work similarly to the typescript-fetch generator. It reads the discriminator field value and does a simple comparison and returns the correct class type.
In the PHP generator it would look like this:
class PetBaseObject implements ModelInterface, ArrayAccess, \JsonSerializable
{
// ...
public static function discriminatorClassName(array $data): ?string
{
if (!array_key_exists('pet_type', $data)) {
return null;
}
if ($data['pet_type'] === 'cat') {
return PetCat::class;
}
if ($data['pet_type'] === 'dog') {
return PetDog::class;
}
if ($data['pet_type'] === 'fish') {
return PetFish::class;
}
return null;
}
In my mind the whole point of passing an array of data to ObjectSerializer::deserialize() is for it to do all instantiation for the user. Otherwise the user would simply do
$cat = new OpenAPI\Client\Model\PetCat();
$cat->setLikesCatnip(true);
Was this choice done on purpose? I have code ready for a PR if it is something you think would be a good addition to the generator:
$ php test.php
object(OpenAPI\Client\Model\PetCat)#3 (1) {
["container":protected]=>
array(2) {
["pet_type"]=>
string(3) "cat"
["likes_catnip"]=>
bool(false)
}
}
@jebentier @dkarlovi @mandrean @jfastnacht @ackintosh @ybelenko @renepardon
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the PHP generator's ObjectSerializer::deserialize() entry point and compare how the typescript-fetch generator handles discriminator values. Use the supplied PetBaseObject, PetCat, PetDog, and PetFish example to verify the expected generated class, then check that the generated PHP models and serializer produce the demonstrated result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, php
- Domain
- backend-api-design, devtools
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100