scramble icon indicating copy to clipboard operation
scramble copied to clipboard

API Resource: example and description are lost for union type

Open petert82 opened this issue 9 months ago • 1 comments

Using v0.12.11, when trying to document an API resource like this:

/**
 * @mixin MyModel
 */
class MyModelResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            /**
             * The first field
             * @var string|null
             * @example "Some example value"
             */
            'field_one' => $this->field_one,
            /**
             * The second field
             * @var string|null|boolean
             * @example "Some other example"
             */
            'field_two' => $this->field_two,
        ];
    }
}

The generated documentation for field_one works as expected, and includes the description from the doc block as well as the given example:

{
  "type": [
    "string",
    "null"
  ],
  "description": "The first field",
  "examples": [
    "Some example value"
  ]
}

However field_two ignores the description and the example, and just documents that it can be any of string, null or boolean:

{
  "anyOf": [
    {
      "type": "string"
    },
    {
      "type": "null"
    },
    {
      "type": "boolean"
    }
  ]
}

I'm not sure if I'm missing a way to annotate the field to make this work they way I would expect for field_two, or if this is a bug?

petert82 avatar Mar 14 '25 11:03 petert82

Coming back to this again on v0.12.19, it seems the issue is actually with any union type that is something other than a plain nullable type, e.g. a var tag like @var string|boolean causes the field to be documented as an anyOf type, without a description or example, like field_two above.

As far as I can tell from some messing around with some static schema json, Stoplight would be happy to render a property defined like:

{
  "anyOf": [
    {
      "type": "string"
    },
    {
      "type": "null"
    },
    {
      "type": "boolean"
    }
  ],
  "description": "blah",
  "example": "some example"
}

petert82 avatar May 05 '25 12:05 petert82

@petert82 cannot reproduce in 0.13.3, maybe it was fixed along the way. Let me know if the issue persists for you on the newest version.

romalytvynenko avatar Nov 16 '25 07:11 romalytvynenko

@romalytvynenko thanks for taking a look!

I just tried on 0.13.4 and while I do now get the description in the generated docs, the value from @example is still not rendered in the user-facing documentation when the type is more complicated than a nullable scalar (though having checked the generated schema, both description & example are now always present in the schema).

e.g. this works as expected:

public function toArray(Request $request): array
    {
        return [
            // date that the token expires
            // @var string|null
            // @example "2025-08-24T14:15:22Z"
            'expires_at' => $token->expires_at,
        ];
    }

and produces:

Image

Relevant part of the generated schema being:

{
  "type": [
    "string",
    "null"
  ],
  "description": "date that the token expires",
  "examples": [
    "2025-08-24T14:15:22Z"
  ]
}

As soon as one more non-null type is added to the type, the value from @example stops rendering, so e.g. with this code:

public function toArray(Request $request): array
    {
        return [
            // date that the token expires
            // @var string|int|null
            // @example "2025-08-24T14:15:22Z"
            'expires_at' => $token->expires_at,
        ];
    }

We get as a result:

Image

Where the schema is now:

{
  "description": "date that the token expires",
  "examples": [
    "2025-08-24T14:15:22Z"
  ],
  "anyOf": [
    {
      "type": "string"
    },
    {
      "type": "integer"
    },
    {
      "type": "null"
    }
  ]
}

I'm not familiar enough with the schema structure to know if this is a Scramble or Stoplight issue, but (assuming I was right when I commented in May) changing examples to example in the new version of the schema would actually let Stoplight render it as expected (though I appreciate this may not a be a change that's possible or desirable to make!).

petert82 avatar Nov 17 '25 13:11 petert82