Skip to main content
Prism Vertex supports structured output (JSON) generation with schema validation across all supported providers. The implementation varies by API schema, but the interface remains consistent.

Basic usage

Generate structured JSON output using a schema:
use Prism\Prism\Prism;
use Prism\Vertex\Enums\Vertex;
use Prism\Prism\Schema\ObjectSchema;
use Prism\Prism\Schema\StringSchema;
use Prism\Prism\Schema\ArraySchema;

$schema = new ObjectSchema(
    name: 'languages',
    description: 'Top programming languages',
    properties: [
        new ArraySchema(
            'languages',
            'List of programming languages',
            items: new ObjectSchema(
                name: 'language',
                description: 'Programming language details',
                properties: [
                    new StringSchema('name', 'The language name'),
                    new StringSchema('popularity', 'Popularity description'),
                ]
            )
        )
    ]
);

$response = Prism::structured()
    ->using(Vertex::Gemini, 'gemini-2.5-flash')
    ->withSchema($schema)
    ->withPrompt('List the top 3 programming languages')
    ->asStructured();

$data = $response->structured;

Schema types

Prism provides several schema types for defining structured output:

String schema

use Prism\Prism\Schema\StringSchema;

$schema = new StringSchema(
    name: 'name',
    description: 'The person\'s name'
);

Array schema

use Prism\Prism\Schema\ArraySchema;
use Prism\Prism\Schema\StringSchema;

$schema = new ArraySchema(
    name: 'tags',
    description: 'List of tags',
    items: new StringSchema('tag', 'A single tag')
);

Object schema

use Prism\Prism\Schema\ObjectSchema;
use Prism\Prism\Schema\StringSchema;
use Prism\Prism\Schema\IntegerSchema;

$schema = new ObjectSchema(
    name: 'person',
    description: 'Person details',
    properties: [
        new StringSchema('name', 'Full name'),
        new IntegerSchema('age', 'Age in years'),
    ]
);

Complete example

Here’s a complete example with nested schemas:
1
Define the schema
2
Create a schema with nested objects and arrays:
3
use Prism\Prism\Schema\ObjectSchema;
use Prism\Prism\Schema\StringSchema;
use Prism\Prism\Schema\ArraySchema;
use Prism\Prism\Schema\IntegerSchema;

$schema = new ObjectSchema(
    name: 'book_analysis',
    description: 'Analysis of a book',
    properties: [
        new StringSchema('title', 'Book title'),
        new StringSchema('author', 'Book author'),
        new IntegerSchema('year', 'Publication year'),
        new ArraySchema(
            'themes',
            'Main themes',
            items: new StringSchema('theme', 'A theme')
        ),
        new ArraySchema(
            'characters',
            'Main characters',
            items: new ObjectSchema(
                name: 'character',
                description: 'Character details',
                properties: [
                    new StringSchema('name', 'Character name'),
                    new StringSchema('role', 'Character role'),
                ]
            )
        ),
    ]
);
4
Generate structured output
5
Use the schema with any provider:
6
use Prism\Prism\Prism;
use Prism\Vertex\Enums\Vertex;

$response = Prism::structured()
    ->using(Vertex::Gemini, 'gemini-2.5-flash')
    ->withSchema($schema)
    ->withPrompt('Analyze the book "1984" by George Orwell')
    ->asStructured();
7
Access the response
8
The response contains the parsed JSON data:
9
$data = $response->structured;

// Access properties
echo $data['title'];        // "1984"
echo $data['author'];       // "George Orwell"
echo $data['year'];         // 1949

// Access arrays
foreach ($data['themes'] as $theme) {
    echo $theme;
}

// Access nested objects
foreach ($data['characters'] as $character) {
    echo $character['name'] . ' - ' . $character['role'];
}

Provider support

All providers support structured output, but the implementation varies:
Native structured outputGoogle Gemini models use native structured output via response_mime_type: application/json and response_schema. The model is constrained to produce valid JSON matching your schema.
$response = Prism::structured()
    ->using(Vertex::Gemini, 'gemini-2.5-flash')
    ->withSchema($schema)
    ->withPrompt('Generate data')
    ->asStructured();
Gemini provides the most reliable structured output with strict schema validation.

Customizing JSON instructions

For Anthropic and OpenAI schemas, you can customize the JSON instruction message:
use Prism\Prism\Prism;
use Prism\Vertex\Enums\Vertex;

$response = Prism::structured()
    ->using(Vertex::Anthropic, 'claude-3-5-sonnet@20241022')
    ->withSchema($schema)
    ->withProviderOptions([
        'jsonModeMessage' => 'Please respond with valid JSON matching the schema provided.',
    ])
    ->withPrompt('Generate data')
    ->asStructured();

Schema implementation by provider

Each API schema handles structured output differently:
SchemaImplementationNative Support
Geminiresponse_mime_type: application/json + response_schemaYes
AnthropicPrompt-based instructionNo
OpenAIresponse_format: { type: "json_object" } + instructionPartial
Despite implementation differences, all providers return valid JSON when using asStructured().

Error handling

Handle invalid schema or generation errors:
use Prism\Prism\Exceptions\PrismException;

try {
    $response = Prism::structured()
        ->using(Vertex::Gemini, 'gemini-2.5-flash')
        ->withSchema($schema)
        ->withPrompt('Generate data')
        ->asStructured();
} catch (PrismException $e) {
    echo 'Error: ' . $e->getMessage();
}

Response object

The asStructured() method returns a Prism\Prism\Structured\Response object:
$response = Prism::structured()
    ->using(Vertex::Gemini, 'gemini-2.5-flash')
    ->withSchema($schema)
    ->withPrompt('Generate data')
    ->asStructured();

// Access the parsed JSON as an array
$data = $response->structured;

// Access usage statistics
echo $response->usage->inputTokens;
echo $response->usage->outputTokens;

// Access the raw response
var_dump($response->response);

Best practices

1
Use descriptive names and descriptions
2
Clear names and descriptions help the model understand what you want:
3
new StringSchema(
    name: 'email',
    description: 'User email address in valid format'
)
4
Start with Gemini for most reliable results
5
Gemini’s native structured output provides the best schema adherence:
6
$response = Prism::structured()
    ->using(Vertex::Gemini, 'gemini-2.5-flash')
    ->withSchema($schema)
    ->withPrompt('Generate data')
    ->asStructured();
7
Test with different providers
8
Different providers may produce different results for the same schema:
9
// Test with multiple providers
$providers = [
    [Vertex::Gemini, 'gemini-2.5-flash'],
    [Vertex::Anthropic, 'claude-3-5-sonnet@20241022'],
    [Vertex::Mistral, 'mistral-small-2503'],
];

foreach ($providers as [$provider, $model]) {
    $response = Prism::structured()
        ->using($provider, $model)
        ->withSchema($schema)
        ->withPrompt('Generate data')
        ->asStructured();
}

Next steps

Text generation

Generate text responses without schema constraints

Embeddings

Create text embeddings for semantic search

Multi-provider

Use multiple providers with different configurations

Build docs developers (and LLMs) love