Skip to content

Wrong return values in Service Mapping Description (SMD) #18

@tbreuss

Description

@tbreuss

Bug Report

The Service Mapping Description (SMD) detects wrong return values under certain (unclear) circumstances.

Q A
PHP 7.4
laminas/laminas-json-server 3.3

Summary

The return value types are kind of multiplied (see below).

I have the following Dummy class, which describes return values via phpdoc as follows.

<?php

declare(strict_types=1);

/**
 * Dummy
 */
class Dummy
{
    /**
     * Method a
     *
     * @param int $x
     * @param float $y
     * @return array
     */
    public function a(int $x, float $y): array
    {
        return ['a'];
    }

    /**
     * Method b
     *
     * @param int|float $x
     * @param string $y
     * @param int|float $z
     * @return object
     */
    public function b($x, $y, $z = 0.0): object
    {
        return (object)['name' => 'b'];
    }

    /**
     * Method c
     *
     * @param int $x
     * @param int $y
     * @param int $z
     * @return array
     */
    public function c(int $x, int $y = 0, int $z = 0): array
    {
        return ['name' => 'c'];
    }

    /**
     * Method d
     *
     * @param int|float $x
     * @param float $y
     * @return array
     */
    public function d(int $x, float $y): array
    {
        return ['d'];
    }
}

The auto-generated Service Mapping Description (SMD) looks like follows.

{
    "transport": "POST",
    "envelope": "JSON-RPC-2.0",
    "contentType": "application\/json",
    "SMDVersion": "2.0",
    "services": {
        "dummy.a": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.a",
            "parameters": [
                {
                    "type": "integer",
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "float",
                    "name": "y",
                    "optional": false
                }
            ],
            "returns": "array"
        },
        "dummy.b": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.b",
            "parameters": [
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "string",
                    "name": "y",
                    "optional": false
                },
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "z",
                    "optional": true,
                    "default": 0
                }
            ],
            "returns": [
                "object",
                "object",
                "object",
                "object",
                "object",
                "object"
            ]
        },
        "dummy.c": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.c",
            "parameters": [
                {
                    "type": "integer",
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "integer",
                    "name": "y",
                    "optional": true,
                    "default": 0
                },
                {
                    "type": "integer",
                    "name": "z",
                    "optional": true,
                    "default": 0
                }
            ],
            "returns": [
                "array",
                "array",
                "array"
            ]
        },
        "dummy.d": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.d",
            "parameters": [
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "float",
                    "name": "y",
                    "optional": false
                }
            ],
            "returns": [
                "array",
                "array"
            ]
        }
    },
    "methods": {
        "dummy.a": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.a",
            "parameters": [
                {
                    "type": "integer",
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "float",
                    "name": "y",
                    "optional": false
                }
            ],
            "returns": "array"
        },
        "dummy.b": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.b",
            "parameters": [
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "string",
                    "name": "y",
                    "optional": false
                },
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "z",
                    "optional": true,
                    "default": 0
                }
            ],
            "returns": [
                "object",
                "object",
                "object",
                "object",
                "object",
                "object"
            ]
        },
        "dummy.c": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.c",
            "parameters": [
                {
                    "type": "integer",
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "integer",
                    "name": "y",
                    "optional": true,
                    "default": 0
                },
                {
                    "type": "integer",
                    "name": "z",
                    "optional": true,
                    "default": 0
                }
            ],
            "returns": [
                "array",
                "array",
                "array"
            ]
        },
        "dummy.d": {
            "envelope": "JSON-RPC-2.0",
            "transport": "POST",
            "name": "dummy.d",
            "parameters": [
                {
                    "type": [
                        "integer",
                        "float"
                    ],
                    "name": "x",
                    "optional": false
                },
                {
                    "type": "float",
                    "name": "y",
                    "optional": false
                }
            ],
            "returns": [
                "array",
                "array"
            ]
        }
    }
}

Current behavior

The return values seems to be multiplied. It looks like there is a relation to the params.

Method Return Conclusion
dummy.a array Ok
dummy.b array of 6 objects strange, why 6 objects?
dummy.c array of 3 arrays strange, why 3 arrays?
dummy.d array of 2 arrays strange, why 2 arrays?

How to reproduce

  • follow the laminas-json-server as described in the documentation
  • create a service class like the one above
  • consume the service map description via the endpoint "GET /json-rpc"

Expected behavior

The return values should not be multiplied.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions