private function createModel(array $model, $location)
    {
        $name = null;
        if (isset($model['id']) === true) {
            // if model id is set, us it as a name
            $name = trim($model['id']);
        } elseif (isset($model['nickname'], $this->responseClasses[$model['nickname']])) {
            // if custom response class is defined with model nickname, use nickname
            $name = $model['nickname'];
        } elseif (isset($model['type']) === true && $model['type'] === 'array') {
            // if model is of array type
            if (isset($model['items']['$ref']) === true) {
                // E. g. if it's an array of 'Tag' models, call this model 'TagList'.
                $name = $model['items']['$ref'].'List';
            } elseif (isset($model['nickname']) === true) {
                // Fallback generate name from operation nickname (e.g. getTags -> TagList)
                $found = preg_match('/[A-Z]/', $model['nickname'], $matches, PREG_OFFSET_CAPTURE);
                if ($found === 1) {
                    $name = rtrim(substr($model['nickname'], $matches[0][1]), 's').'List';
                }
            }
        }
        // if none of above worked to create a model name, hash model array
        if ($name === null) {
            $name = $model['id'] = 'anon_'.self::hashArray($model);
        }

        // a model is basically a parameter, but has name property added
        $defaults = [
            'name' => $name,
            'type' => 'object',
        ];
        /** @noinspection AdditionOperationOnArraysInspection */
        $data = $this->transformSchema($model + $defaults);
        if ('object' === $data['type']) {
            $data['additionalProperties'] = false;
            // model must have top level properties specified as serialized response type, but no response type itself
            foreach ($data['properties'] as $key => $property) {
                $data['properties'][$key]['location'] = $location;
            }
        } elseif ('array' === $data['type']) {
            $data['location'] = $location;
        }

        // allow result class override
        if (isset($this->responseClasses[$name])) {
            $class = $this->responseClasses[$name];
            $data['class'] = $class;

            if (is_subclass_of($class, ResultInterface::class)) {
                $data['type'] = 'object';
                if (is_array($data['additionalProperties']) === false) {
                    $data['additionalProperties'] = [];
                }
                $data['additionalProperties']['location'] = $location;
            } else {
                $data['type'] = 'class';
            }
        }

        // required makes no sense at root of model
        unset($data['required']);

        return new Parameter($data, ['description' => $this->getServiceDescription()]);
    }