Skip to content

[PHP] Serializing maps #5338

Closed
Closed
@pminten

Description

@pminten
Description

When serializing a map object (type object with additionalProperties) in a generated PHP client additional keys not explicitly declared in the spec are ignored.

Swagger-codegen version

2.2.2, the problem also exists in the master branch at abffdca (current tip of master).

Swagger declaration file content or url

This is a definition which I stole from from another issue but it nicely demonstrates the problem.

{
  "swagger": "2.0",
  "info": {
    "version": "0.0.1",
    "title": "test of Swagger with boolean additionalProperties in schema definition"
  },
  "paths": {
    "/": {
      "get": {
        "produces": [ "application/json" ],
        "description": "xxx",
        "responses": {
          "200": {
            "schema": { "$ref": "#/definitions/Root" }
          }
        }
      }
    }
  },
  "definitions": {
    "Root": {
      "type": "object",
      "properties": {
        "foo": {
          "type": "string"
        }
      },
      "additionalProperties": false
    }
  }
}
Command line used for generation

java -jar $SWAGGER_CODEGEN_CHECKOUT/modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -l php -i input.json -o generated

Steps to reproduce

I have a simple PHP file:

<?php
require 'SwaggerClient-php/autoload.php';
$serializer = new Swagger\Client\ObjectSerializer();
var_dump($serializer->sanitizeForSerialization(new \Swagger\Client\Model\Root(["a" => "b", "c" => "d", "foo" => "bar"])));

Running this (no arguments or anything needed) produces:

object(stdClass)#4 (1) {
  ["foo"]=>
  string(3) "bar"
}

I would expect a mapping type to contain all keys and values passed to it (keys "a" and "c" and associated values). Because it doesn't all key/value pairs not declared explicitly in the spec will not be encoded and thus not be sent to the server, defeating the point of additionalProperties.

Related issues

Couldn't find any.

Suggest a Fix

Based on how ObjectSerializer works it would seem sensible to have the generated model class simply store all key/value pairs somewhere and make them visible through swaggerTypes() and getters()/setters(). However there are a few problems with that. One is that setters returns an array which is typically immediately indexed into, that will cause problems if you define a new key. This can be solved by having setters return an array-like object instead with some magic behavior. The second problem is that ObjectSerializer will again use swaggerTypes() to figure out which properties to set upon deserialization. Of course swaggerTypes can't know all the properties beforehand on a map so this will miss stuff on deserialization.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions