---
title: 構造化出力
url: https://platform.claude.com/docs/ja/build-with-claude/structured-outputs
description: エージェントワークフローから検証済みのJSON結果を取得する
featureMetadata:
  status: ga
  zdr:
    eligibility: eligible
    note: Excludes [Covered Models](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements).
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-sonnet-4-5-20250929
    - claude-opus-4-5-20251101
    - claude-haiku-5-5
    - claude-haiku-4-5-20251001
  supportedPlatforms:
    Claude API: ga
    Claude Platform on AWS: ga
    Amazon Bedrock:
      availability: ga
      note: Amazon Bedrockでは、構造化出力はClaude Opus 4.6、Claude Sonnet 4.6、Claude Sonnet 4.5、Claude Opus 4.5、Claude Haiku 4.5向けのレガシーな[Amazon Bedrock（Opus 4.6以前）](https://platform.claude.com/docs/ja/build-with-claude/claude-on-amazon-bedrock-legacy)統合で利用可能であり、[Claude in Amazon Bedrock](https://platform.claude.com/docs/ja/build-with-claude/claude-in-amazon-bedrock)では利用できません。
    Google Cloud: ga
    Microsoft Foundry: ga
---

「structured outputs」（構造化出力）は、Claudeの応答が特定のスキーマに従うように制約し、下流の処理のために有効で解析可能な出力を保証します。構造化出力は、相互に補完する2つの機能を提供します。

* **「JSON outputs」（JSON出力）**（`output_config.format`）：Claudeの応答を特定のJSON形式で取得します。たとえば、画像やテキストからのデータ抽出、構造化レポートの生成、API応答のフォーマットなどに使用できます。このページではJSON出力について説明します。
* **「Strict tool use」（厳密なツール使用）**（`strict: true`）：ツール名と入力に対するスキーマ検証を保証します。[厳密なツール使用](https://platform.claude.com/docs/ja/agents-and-tools/tool-use/strict-tool-use)を参照してください。

これらの機能は個別に使用することも、[同じリクエスト内で併用する](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#using-both-features-together)こともできます。

## 構造化出力を使用する理由

構造化出力がない場合、Claudeは不正な形式のJSON応答や無効なツール入力を生成し、アプリケーションを壊してしまう可能性があります。慎重にプロンプトを作成しても、次のような問題に遭遇することがあります。

* 無効なJSON構文による解析エラー
* 必須フィールドの欠落
* 一貫性のないデータ型
* エラー処理と再試行を必要とするスキーマ違反

構造化出力は、「constrained decoding」（制約付きデコーディング）によってスキーマに準拠した応答を保証します。

* **常に有効：** `JSON.parse()`エラーはもう発生しません
* **型安全：** フィールドの型と必須フィールドが保証されます
* **信頼性：** スキーマ違反による再試行は不要です

## 仕組み

<Steps>
  <Step title="スキーマを定義する">
    必要な構造をJSONスキーマとして、または使用する言語の型として記述します。スキーマはJSON Schemaに従いますが、いくつかの[制限](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)があります。
  </Step>

  <Step title="output_config.formatで送信する">
    リクエストは、`type: "json_schema"`を指定した`output_config.format`にスキーマを含めます。SDKヘルパーがこれを自動的に設定します。
  </Step>

  <Step title="応答を読み取る">
    Claudeは、スキーマに一致する有効なJSONを応答のテキストコンテンツブロックで返します。SDKヘルパーはそれを指定した型にパースします。
  </Step>
</Steps>

## 使用方法

<Tabs>
  <Tab title="cURL">
    ```bash
    curl https://api.anthropic.com/v1/messages \
      -H "content-type: application/json" \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -d '{
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "Extract the key information from this email: John Smith (john@example.com) is interested in our Enterprise plan and wants to schedule a demo for next Tuesday at 2pm."
          }
        ],
        "output_config": {
          "format": {
            "type": "json_schema",
            "schema": {
              "type": "object",
              "properties": {
                "name": {"type": "string"},
                "email": {"type": "string"},
                "plan_interest": {"type": "string"},
                "demo_requested": {"type": "boolean"}
              },
              "required": ["name", "email", "plan_interest", "demo_requested"],
              "additionalProperties": false
            }
          }
        }
      }'
    ```

    Claudeは、応答のテキストコンテンツブロックで次のようなJSONを返します。

    ```json Output
    {
      "name": "John Smith",
      "email": "john@example.com",
      "plan_interest": "Enterprise",
      "demo_requested": true
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash
    ant messages create \
      --transform 'content.#(type=="text").text|@fromstr' \
      --format jsonl <<'YAML'
    model: claude-opus-5-5
    max_tokens: 1024
    messages:
      - role: user
        content: >-
          Extract the key information from this email: John Smith
          (john@example.com) is interested in our Enterprise plan and wants
          to schedule a demo for next Tuesday at 2pm.
    output_config:
      format:
        type: json_schema
        schema:
          type: object
          properties:
            name: {type: string}
            email: {type: string}
            plan_interest: {type: string}
            demo_requested: {type: boolean}
          required: [name, email, plan_interest, demo_requested]
          additionalProperties: false
    YAML
    ```

    JSON出力の一部のプロパティのみを出力するには、[GJSONパス](https://platform.claude.com/docs/ja/cli-sdks-libraries/cli/using#transform-output-with-gjson)を`--transform`に渡します。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Python">
    ```python
    from pydantic import BaseModel
    # ...


    class ContactInfo(BaseModel):
        name: str
        email: str
        plan_interest: str
        demo_requested: bool


    client = Anthropic()

    response = client.messages.parse(
        model="claude-opus-5-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": (
                    "Extract the key information from this email: "
                    "John Smith (john@example.com) is interested in our Enterprise plan "
                    "and wants to schedule a demo for next Tuesday at 2pm."
                ),
            }
        ],
        output_format=ContactInfo,
    )

    print(response.parsed_output)
    ```

    推奨されるメソッドである`client.messages.parse()`に、[Pydantic](https://docs.pydantic.dev/)モデルを`output_format`として渡します。SDKはモデルのスキーマを変換し、`output_config.format`として送信し、応答を検証して、パースされたモデルを`parsed_output`で返します。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    name='John Smith' email='john@example.com' plan_interest='Enterprise' demo_requested=True
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    import { z } from "zod";
    import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

    const ContactInfoSchema = z.object({
      name: z.string(),
      email: z.string(),
      plan_interest: z.string(),
      demo_requested: z.boolean()
    });

    const client = new Anthropic();

    const response = await client.messages.parse({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content:
            "Extract the key information from this email: " +
            "John Smith (john@example.com) is interested in our Enterprise plan " +
            "and wants to schedule a demo for next Tuesday at 2pm."
        }
      ],
      output_config: { format: zodOutputFormat(ContactInfoSchema) }
    });

    // 自動的に解析および検証されます
    console.log(response.parsed_output);
    ```

    [Zod](https://zod.dev/)スキーマを`zodOutputFormat()`でラップし、`output_config.format`として`client.messages.parse()`に渡します。`zodOutputFormat()`はスキーマを変換し、`parse()`は応答を検証して、スキーマに一致する型付きのパース結果を`parsed_output`で返します。

    上記の例の出力は次のとおりです。

    ```javascript Output
    {
      name: 'John Smith',
      email: 'john@example.com',
      plan_interest: 'Enterprise',
      demo_requested: true
    }
    ```
  </Tab>

  <Tab title="C#">
    ```csharp
    using Anthropic;
    using Anthropic.Models.Messages;
    using Anthropic.Services;

    var client = new AnthropicClient();

    var response = await client.Messages.Create<ContactInfo>(new MessageCreateParams
    {
        Model = Model.ClaudeOpus5_5,
        MaxTokens = 1024,
        Messages = [new() {
            Role = Role.User,
            Content = "Extract the key information from this email: "
                + "John Smith (john@example.com) is interested in our Enterprise plan "
                + "and wants to schedule a demo for next Tuesday at 2pm."
        }],
    });

    if (response.Content.Select(block => block.Parsed()).OfType<ContactInfo>().FirstOrDefault() is { } contact)
    {
        Console.WriteLine(contact);
    }

    public record ContactInfo
    {
        public string Name { get; set; } = "";
        public string Email { get; set; } = "";
        public string PlanInterest { get; set; } = "";
        public bool DemoRequested { get; set; }
    }
    ```

    プレーンなC#のクラスまたはレコードを、ジェネリックな`Create<T>()`オーバーロードに渡します。SDKは型からJSONスキーマを導出して変換し、各テキストブロックをその型にパースし直します。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    ContactInfo { Name = John Smith, Email = john@example.com, PlanInterest = Enterprise, DemoRequested = True }
    ```
  </Tab>

  <Tab title="Go">
    ```go
    type ContactInfo struct {
    	Name          string `json:"name"`
    	Email         string `json:"email"`
    	PlanInterest  string `json:"plan_interest"`
    	DemoRequested bool   `json:"demo_requested"`
    }

    func main() {
    	client := anthropic.NewClient()

    	var contact ContactInfo
    	_, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
    		Model:     anthropic.ModelClaudeOpus5_5,
    		MaxTokens: 1024,
    		Messages: []anthropic.BetaMessageParam{
    			anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(
    				"Extract the key information from this email: " +
    					"John Smith (john@example.com) is interested in our Enterprise plan " +
    					"and wants to schedule a demo for next Tuesday at 2pm.",
    			)),
    		},
    		OutputConfig: anthropic.BetaOutputConfigParam{
    			Format: anthropic.BetaJSONOutputFormatParam{Schema: &contact},
    		},
    	})
    	if err != nil {
    		panic(err)
    	}

    	fmt.Printf("%#v\n", contact)
    }
    ```

    <Note>
      Goでは構造体をスキーマとして渡す機能はベータ版であるため、この例では`client.Beta.Messages.New`を使用しています。GAの`client.Messages.New`を使用するには、[生のJSONスキーマの使用](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#using-a-raw-json-schema)に示すようにJSONスキーマを渡してください。
    </Note>

    SDKは構造体からJSONスキーマを生成・変換し、応答をその構造体にアンマーシャルします。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    main.ContactInfo{Name:"John Smith", Email:"john@example.com", PlanInterest:"Enterprise", DemoRequested:true}
    ```
  </Tab>

  <Tab title="Java">
    ```java
    static class ContactInfo {
        public String name;
        public String email;
        public String plan_interest;
        public boolean demo_requested;
    }

    void main() throws Exception {
        AnthropicClient client = AnthropicOkHttpClient.fromEnv();

        StructuredMessageCreateParams<ContactInfo> params = MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_5_5)
            .maxTokens(1024)
            .addUserMessage("Extract the key information from this email: "
                + "John Smith (john@example.com) is interested in our Enterprise plan "
                + "and wants to schedule a demo for next Tuesday at 2pm.")
            .outputConfig(ContactInfo.class)
            .build();

        StructuredMessage<ContactInfo> response = client.messages().create(params);
        ContactInfo contact = response.content().stream()
            .flatMap(block -> block.text().stream())
            .findFirst().orElseThrow().text();
        IO.println(new ObjectMapper().writeValueAsString(contact));
    }
    ```

    Javaクラスを`outputConfig()`に渡すと、SDKはそこからJSONスキーマを導出し、スキーマを検証します。その後、ビルダーは`StructuredMessageCreateParams<T>`を生成します。SDKはスキーマを変換するのではなく、ローカル検証によって[APIでサポートされていない制約](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)を拒否します。パース結果は`response.content().stream().flatMap(block -> block.text().stream()).findFirst().orElseThrow().text()`で読み取ります。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```

    <Note>
      スキーマクラスはトップレベルクラスまたは`static`なネストクラスとして宣言してください。この要件はJackson Databindライブラリ（`com.fasterxml.jackson.databind`）に由来します。SDKはこのライブラリを使用してJSON応答をクラスインスタンスにデシリアライズしますが、このライブラリは非staticな内部クラスをインスタンス化できません。
    </Note>

    <Accordion title="ジェネリック型の消去">
      Javaはクラスのメタデータ内のフィールドについてはジェネリック型情報を保持しますが、他のスコープではジェネリック型の消去が適用されます。`List<Book>`型の`BookList.books`フィールドからはJSONスキーマを導出できますが、同じ型のローカル変数からは有効なJSONスキーマを導出できません。

      JSON応答をJavaクラスインスタンスに変換する際にエラーが発生した場合、診断を支援するためにエラーメッセージにJSON応答が含まれます。JSON応答に機密情報が含まれる可能性がある場合は、直接ログに記録しないようにするか、エラーメッセージから機密情報を確実に削除してください。
    </Accordion>

    <Accordion title="ローカルスキーマ検証">
      構造化出力は[JSON Schema言語のサブセット](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)をサポートします。SDKはこのサブセットに合わせてクラスからスキーマを自動生成します。`outputConfig(Class<T>)`メソッドは、指定されたクラスから導出されたスキーマに対して検証チェックを実行します。

      主なポイント：

      * **ローカル検証**は、リモートのAIモデルにリクエストを送信せずに行われます。
      * **リモート検証**も、JSONスキーマを受信した際にAIモデルによって実行されます。
      * **バージョン互換性：** SDKのバージョンが古い場合、ローカル検証が失敗してもリモート検証が成功することがあります。
      * **ローカル検証の無効化：** 互換性の問題が発生した場合は`JsonSchemaLocalValidation.NO`を渡します。

      ```java
      import com.anthropic.core.JsonSchemaLocalValidation;
      // ...

      static class BookList {
          public List<String> books;
      }

      void main() {
          StructuredMessageCreateParams<BookList> createParams = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(2048)
              .outputConfig(BookList.class, JsonSchemaLocalValidation.NO)
              .addUserMessage("List some famous late twentieth century novels.")
              .build();
      }
      ```
    </Accordion>

    <Accordion title="ストリーミング">
      構造化出力はストリーミングでも動作します。応答はストリームイベントで到着するため、JSONをデシリアライズする前に完全な応答を蓄積する必要があります。

      `MessageAccumulator`を使用してストリームからJSON文字列を収集します。蓄積が完了したら、`MessageAccumulator.message(Class<T>)`を呼び出して蓄積された`Message`を`StructuredMessage`に変換します。これによりJSONが自動的にJavaクラスにデシリアライズされます。
    </Accordion>

    <Accordion title="JSONスキーマのプロパティ">
      SDKがJavaクラスからJSONスキーマを導出する際、デフォルトでは`public`フィールドまたは`public`ゲッターメソッドで表されるすべてのプロパティを含め、非`public`のフィールドとゲッターメソッドは除外します。

      アノテーションで可視性を制御できます。

      * `@JsonIgnore`は`public`フィールドまたはゲッターメソッドを除外します
      * `@JsonProperty`は非`public`のフィールドまたはゲッターメソッドを含めます

      `public`ゲッターメソッドを持つ`private`フィールドを定義した場合、SDKはゲッターからプロパティ名を導出します（例えば、`private`フィールド`myValue`と`public`メソッド`getMyValue()`は`"myValue"`プロパティを生成します）。慣例に従わないゲッター名を使用するには、メソッドに`@JsonProperty`アノテーションを付けます。

      各クラスはJSONスキーマ用に少なくとも1つのプロパティを定義する必要があります。次のような場合など、スキーマプロパティを生成できるフィールドやゲッターメソッドがない場合は検証エラーが発生します。

      * クラスにフィールドもゲッターメソッドもない
      * すべての`public`メンバーに`@JsonIgnore`アノテーションが付いている
      * すべての非`public`メンバーに`@JsonProperty`アノテーションがない
      * フィールドが`Map`型を使用しており、空の`"properties"`フィールドが生成される
    </Accordion>

    <Accordion title="コンポジションと継承">
      JavaクラスはJSONスキーマを定義する際に、コンポジションと継承を使用して構造を共有できます。各パターンは出力構造に異なる影響を与えます。

      **コンポジション**はネストされたJSON出力を生成します。`A`と`B`をコンポジションするクラス`Composed`からスキーマを導出する場合：

      ```java
      static class A {
          public String a;
      }

      static class B {
          public String b;
      }

      static class Composed {
          public A composedA;
          public B composedB;
      }
      ```

      JSON出力は次のようなネスト構造になります。

      ```json
      {
        "composedA": { "a": "hello" },
        "composedB": { "b": "world" }
      }
      ```

      **継承**はフラットなJSON出力を生成します。`Base`を拡張するクラス`Derived`からスキーマを導出する場合：

      ```java
      static class Base {
          public String a;
      }

      static class Derived extends Base {
          public String b;
      }
      ```

      JSON出力は次のようなフラット構造になります。

      ```json
      {
        "a": "hello",
        "b": "world"
      }
      ```
    </Accordion>

    <Accordion title="アノテーション（JacksonとSwagger）">
      Jackson Databindアノテーションを使用して、Javaクラスから導出されるJSONスキーマを充実させることができます。

      ```java
      import com.fasterxml.jackson.annotation.JsonClassDescription;
      import com.fasterxml.jackson.annotation.JsonIgnore;
      import com.fasterxml.jackson.annotation.JsonPropertyDescription;

      static class Person {

        @JsonPropertyDescription("The first name and surname of the person")
        public String name;

        public int birthYear;

        @JsonPropertyDescription("The year the person died, or 'present' if the person is living.")
        public String deathYear;
      }

      @JsonClassDescription("The details of one published book")
      static class Book {

        public String title;
        public Person author;

        @JsonPropertyDescription("The year in which the book was first published.")
        public int publicationYear;

        @JsonIgnore
        public String genre;
      }

      static class BookList {
        public List<Book> books;
      }
      ```

      アノテーションの概要：

      * `@JsonClassDescription`：クラスに説明を追加します
      * `@JsonPropertyDescription`：フィールドまたはゲッターメソッドに説明を追加します
      * `@JsonIgnore`：`public`フィールドまたはゲッターをスキーマから除外します
      * `@JsonProperty`：非`public`のフィールドまたはゲッターをスキーマに含めます

      `@JsonProperty(required = false)`を使用した場合、SDKは`false`の値を無視します。クラスから導出されたスキーマは常にすべてのプロパティを必須としてマークします。

      型固有の制約には、Swagger Core（OpenAPI 3）の`@Schema`および`@ArraySchema`アノテーションも使用できます。

      ```java
      import io.swagger.v3.oas.annotations.media.ArraySchema;
      import io.swagger.v3.oas.annotations.media.Schema;

      static class Article {

        @ArraySchema(minItems = 1)
        public List<String> authors;

        public String title;

        @Schema(format = "date")
        public String publicationDate;

        public int pageCount;
      }
      ```

      ローカル検証はサポートされていない制約キーワードを使用していないことをチェックしますが、制約の値はローカルでは検証されません。例えば、サポートされていない`"format"`値はローカル検証を通過しても、リモートでエラーになる可能性があります。

      JacksonとSwaggerの両方のアノテーションを使用して同じスキーマフィールドを設定した場合、Jacksonアノテーションが優先されます。
    </Accordion>
  </Tab>

  <Tab title="PHP">
    ```php
    use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
    use Anthropic\Lib\Contracts\StructuredOutputModel;

    $client = new Client();

    class ContactInfo implements StructuredOutputModel
    {
        use StructuredOutputModelTrait;

        public string $name;
        public string $email;
        public string $plan_interest;
        public bool $demo_requested;
    }

    $message = $client->messages->create(
        maxTokens: 1024,
        messages: [
            [
                'role' => 'user',
                'content' => 'Extract the key information from this email: '
                    . 'John Smith (john@example.com) is interested in our Enterprise plan '
                    . 'and wants to schedule a demo for next Tuesday at 2pm.',
            ],
        ],
        model: 'claude-opus-5-5',
        outputConfig: ['format' => ContactInfo::class],
    );

    $contact = $message->parsedOutput();
    if ($contact instanceof ContactInfo) {
        var_dump($contact);
    }
    ```

    `StructuredOutputModel`を実装し、`StructuredOutputModelTrait`を使用するクラスを定義して、その名前を`outputConfig: ['format' => MyClass::class]`で渡します。SDKはクラスのPHP 8プロパティ型からJSONスキーマを導出して変換し、`$message->parsedOutput()`から型付きのインスタンスを返します。

    `parsedOutput()`は成功時にモデルインスタンスを返し、解析に失敗した場合は`null`（またはエラー配列）を返します。フィールドにアクセスする前に`instanceof`を使用して型を絞り込んでください。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    object(ContactInfo)#42 (4) {
      ["name"]=>
      string(10) "John Smith"
      ["email"]=>
      string(16) "john@example.com"
      ["plan_interest"]=>
      string(10) "Enterprise"
      ["demo_requested"]=>
      bool(true)
    }
    ```

    <Accordion title="型推論">
      SDKはネイティブなPHP 8のプロパティ型をJSON Schemaにマッピングします。

      | PHPの型                           | JSON Schema         |
      | ------------------------------- | ------------------- |
      | `string`                        | `"string"`          |
      | `int`                           | `"integer"`         |
      | `float`                         | `"number"`          |
      | `bool`                          | `"boolean"`         |
      | `array`                         | `"array"`（以下の注記を参照） |
      | `?type`（nullable）               | オプションフィールド          |
      | `StructuredOutputModel`を実装するクラス | ネストされたオブジェクト        |

      `array`プロパティの場合、SDKは要素型がネストされた`StructuredOutputModel`であり、`#[Constrained(itemClass: MyModel::class)]`または`/** @var MyModel[] */`ドックブロックで宣言されている場合にのみ`items`スキーマを追加します。スカラーの配列（`string[]`、`int[]`）は制約のない`{"type":"array"}`を出力します。

      nullableでないすべてのプロパティは必須フィールドになります。
    </Accordion>

    <Accordion title="#[Constrained]属性による制約">
      `#[Constrained]`属性で制約を追加します。

      ```php
      use Anthropic\Lib\Attributes\Constrained;
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      class Address implements StructuredOutputModel { use StructuredOutputModelTrait; public string $street; }

      class Profile implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          #[Constrained(description: 'Age in years', minimum: 0, maximum: 150)]
          public int $age;

          #[Constrained(format: 'email')]
          public string $email;

          #[Constrained(itemClass: Address::class, minItems: 1)]
          public array $addresses;
      }
      ```

      **APIで強制される制約**（スキーマで送信される）：`description`、`format`、`const`、`itemClass`、`minItems`（0または1のみ）。

      **SDKで検証される制約**（送信スキーマから削除され、説明に追記され、応答に対して検証される）：`minimum`、`maximum`、`multipleOf`、`minLength`、`maxLength`。
    </Accordion>
  </Tab>

  <Tab title="Ruby">
    ```ruby
    client = Anthropic::Client.new

    class ContactInfo < Anthropic::BaseModel
      required :name, String
      required :email, String
      required :plan_interest, String
      required :demo_requested, Anthropic::Boolean
    end

    message = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [{
        role: "user",
        content: "Extract the key information from this email: " \
          "John Smith (john@example.com) is interested in our Enterprise plan " \
          "and wants to schedule a demo for next Tuesday at 2pm."
      }],
      output_config: {format: ContactInfo}
    )

    contact = message.parsed_output
    puts contact
    ```

    `Anthropic::BaseModel`を継承するクラスを定義し、`output_config: {format: Model}`として`messages.create()`に渡します。SDKはクラスからJSONスキーマを導出して変換し、パース結果を型付きのRubyオブジェクトとして応答の`parsed_output`属性に割り当てます。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {name: "John Smith", email: "john@example.com", plan_interest: "Enterprise", demo_requested: true}
    ```

    <Accordion title="高度なモデル機能">
      Ruby SDKは、より豊かなスキーマのための追加のモデル定義機能をサポートしています。

      * **`doc:`キーワード：** より情報量の多いスキーマ出力のためにフィールドに説明を追加します
      * **`Anthropic::ArrayOf[T]`：** 型付き配列。配列レベルの制約（`min_items:`、`max_items:`）は`ArrayOf`自体ではなく、`required`/`optional`のキーワードとして渡します
      * **`Anthropic::EnumOf[:a, :b]`：** 制約された値を持つ列挙フィールド
      * **`Anthropic::UnionOf[T1, T2]`：** `anyOf`にマッピングされるユニオン型

      ```ruby
      class FamousNumber < Anthropic::BaseModel
        required :value, Float
        optional :reason, String, doc: "why is this number mathematically significant?"
      end

      class Output < Anthropic::BaseModel
        required :numbers, Anthropic::ArrayOf[FamousNumber], min_items: 3, max_items: 5
      end

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: [{role: "user", content: "give me some famous numbers"}],
        output_config: {format: Output}
      )

      message.parsed_output
      # => #<Output numbers=[#<FamousNumber value=3.14159... reason="Pi is...">...]>
      ```
    </Accordion>
  </Tab>
</Tabs>

## SDKによる変換の仕組み

ほとんどのSDKヘルパーは、サポートされていない機能を使用するスキーマを変換します。変換の手順は次のとおりです。

1. **サポートされていない制約を削除する**（たとえば、`minimum`、`maximum`、`minLength`、`maxLength`）
2. **説明を更新する**：サポートされていない各制約をフィールドの説明に追加します（たとえば、`{minimum: 100}`）
3. すべてのオブジェクト&#x306B;**`additionalProperties: false`を追加する**
4. **文字列フォーマットをフィルタリング**し、サポートされているもののみに絞り込む
5. ヘルパーが応答を検証する場合は、元のスキーマとそのすべての制約に対して**応答を検証する**

Claudeは簡略化されたスキーマを受け取りますが、応答を検証するヘルパーは、コード内のすべての制約を引き続き適用します。

**例：** `minimum: 100`を持つフィールドは、送信されるスキーマでは単純な整数になり、SDKはフィールドの説明に`{minimum: 100}`を追加します。応答を検証するヘルパーは、引き続き`minimum: 100`に対して応答をチェックします。

## 生のJSONスキーマの使用

ファイル、OpenAPI仕様、または実行時にスキーマを構築するコードから得たJSONスキーマを使用するには、それを`output_config.format`で渡します。

<Tabs>
  <Tab title="cURL">
    ```bash
    curl https://api.anthropic.com/v1/messages \
      -H "content-type: application/json" \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -d '{
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "Extract the key information from this email: John Smith (john@example.com) is interested in our Enterprise plan and wants to schedule a demo for next Tuesday at 2pm."
          }
        ],
        "output_config": {
          "format": {
            "type": "json_schema",
            "schema": {
              "type": "object",
              "properties": {
                "name": {"type": "string"},
                "email": {"type": "string"},
                "plan_interest": {"type": "string"},
                "demo_requested": {"type": "boolean"}
              },
              "required": ["name", "email", "plan_interest", "demo_requested"],
              "additionalProperties": false
            }
          }
        }
      }'
    ```

    Claudeは、応答のテキストコンテンツブロックで次のようなJSONを返します。

    ```json Output
    {
      "name": "John Smith",
      "email": "john@example.com",
      "plan_interest": "Enterprise",
      "demo_requested": true
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash
    ant messages create \
      --transform 'content.#(type=="text").text|@fromstr' \
      --format jsonl <<'YAML'
    model: claude-opus-5-5
    max_tokens: 1024
    messages:
      - role: user
        content: >-
          Extract the key information from this email: John Smith
          (john@example.com) is interested in our Enterprise plan and wants
          to schedule a demo for next Tuesday at 2pm.
    output_config:
      format:
        type: json_schema
        schema:
          type: object
          properties:
            name: {type: string}
            email: {type: string}
            plan_interest: {type: string}
            demo_requested: {type: boolean}
          required: [name, email, plan_interest, demo_requested]
          additionalProperties: false
    YAML
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Python">
    ```python
    client = anthropic.Anthropic()

    response = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": (
                    "Extract the key information from this email: "
                    "John Smith (john@example.com) is interested in our Enterprise plan "
                    "and wants to schedule a demo for next Tuesday at 2pm."
                ),
            }
        ],
        output_config={
            "format": {
                "type": "json_schema",
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "email": {"type": "string"},
                        "plan_interest": {"type": "string"},
                        "demo_requested": {"type": "boolean"},
                    },
                    "required": ["name", "email", "plan_interest", "demo_requested"],
                    "additionalProperties": False,
                },
            }
        },
    )
    text = next(block.text for block in response.content if block.type == "text")
    contact = json.loads(text)
    print(contact)
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {'name': 'John Smith', 'email': 'john@example.com', 'plan_interest': 'Enterprise', 'demo_requested': True}
    ```

    [APIでサポートされていない制約](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)をフィールドの説明に移すには、送信前に`anthropic`パッケージの`transform_schema()`にスキーマを通し、必要に応じて結果を編集してください。`transform_schema()`はPydanticモデルも受け付けます。`client.messages.parse()`とは異なり、スキーマを送信するのではなく、変換されたスキーマを返します。
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    import { jsonSchemaOutputFormat } from "@anthropic-ai/sdk/helpers/json-schema";

    const client = new Anthropic();

    const response = await client.messages.parse({
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content: "Extract contact info: John Smith, john@example.com, interested in the Pro plan"
        }
      ],
      output_config: {
        format: jsonSchemaOutputFormat({
          type: "object",
          properties: {
            name: { type: "string" },
            email: { type: "string" },
            planInterest: { type: "string" }
          },
          required: ["name", "email", "planInterest"],
          additionalProperties: false
        } as const)
      }
    });

    // response.parsed_output の型は { name: string; email: string; planInterest: string } | null です
    console.log(response.parsed_output);
    ```

    ZodをインストールせずにプレーンなJSONスキーマを`parse()`に渡すには、`jsonSchemaOutputFormat()`を使用します。APIはスキーマに準拠した応答を返し、スキーマを`as const`で宣言した場合、`parsed_output`の型はスキーマに従ってTypeScriptによって自動的に推論されます。インポートまたは生成されたスキーマの場合、`parsed_output`の型は`unknown`になります。

    デフォルトでは、このヘルパーは`zodOutputFormat()`と同じ方法で[スキーマを変換](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#how-sdk-transformation-works)します。変更せずに送信するには、2番目の引数として`{ transform: false }`を渡します。`zodOutputFormat()`とは異なり、応答を検証しないため、`minimum`などの[APIでサポートされていない制約](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)の違反は検出されません。

    上記の例の出力は次のとおりです。

    ```javascript Output
    { name: 'John Smith', email: 'john@example.com', planInterest: 'Pro' }
    ```
  </Tab>

  <Tab title="C#">
    ```csharp
    using System.Text.Json;
    using Anthropic;
    using Anthropic.Models.Messages;

    var client = new AnthropicClient();

    var response = await client.Messages.Create(new MessageCreateParams
    {
        Model = Model.ClaudeOpus5_5,
        MaxTokens = 1024,
        Messages = [new() {
            Role = Role.User,
            Content = "Extract the key information from this email: "
                + "John Smith (john@example.com) is interested in our Enterprise plan "
                + "and wants to schedule a demo for next Tuesday at 2pm."
        }],
        OutputConfig = new OutputConfig
        {
            Format = new JsonOutputFormat
            {
                Schema = new Dictionary<string, JsonElement>
                {
                    ["type"] = JsonSerializer.SerializeToElement("object"),
                    ["properties"] = JsonSerializer.SerializeToElement(new
                    {
                        name = new { type = "string" },
                        email = new { type = "string" },
                        plan_interest = new { type = "string" },
                        demo_requested = new { type = "boolean" },
                    }),
                    ["required"] = JsonSerializer.SerializeToElement(
                        new[] { "name", "email", "plan_interest", "demo_requested" }),
                    ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                },
            },
        },
    });

    if (response.Content.Select(b => b.Value).OfType<TextBlock>().FirstOrDefault() is { } textBlock)
    {
        // JSON はスキーマに一致することが保証されています
        var contact = JsonSerializer.Deserialize<JsonElement>(textBlock.Text);
        Console.WriteLine(contact);
    }
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise","demo_requested":true}
    ```
  </Tab>

  <Tab title="Go">
    ```go
    type ContactInfo struct {
    	Name          string `json:"name"`
    	Email         string `json:"email"`
    	PlanInterest  string `json:"plan_interest"`
    	DemoRequested bool   `json:"demo_requested"`
    }

    func main() {
    	client := anthropic.NewClient()

    	message, _ := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
    		Model:     anthropic.ModelClaudeOpus5_5,
    		MaxTokens: 1024,
    		Messages: []anthropic.MessageParam{
    			anthropic.NewUserMessage(anthropic.NewTextBlock(
    				"Extract the key information from this email: " +
    					"John Smith (john@example.com) is interested in our Enterprise plan " +
    					"and wants to schedule a demo for next Tuesday at 2pm.",
    			)),
    		},
    		OutputConfig: anthropic.OutputConfigParam{
    			Format: anthropic.JSONOutputFormatParam{
    				Schema: map[string]any{
    					"type": "object",
    					"properties": map[string]any{
    						"name":           map[string]string{"type": "string"},
    						"email":          map[string]string{"type": "string"},
    						"plan_interest":  map[string]string{"type": "string"},
    						"demo_requested": map[string]string{"type": "boolean"},
    					},
    					"required":             []string{"name", "email", "plan_interest", "demo_requested"},
    					"additionalProperties": false,
    				},
    			},
    		},
    	})

    	for _, block := range message.Content {
    		switch variant := block.AsAny().(type) {
    		case anthropic.TextBlock:
    			var contact ContactInfo
    			json.Unmarshal([]byte(variant.Text), &contact)
    			fmt.Printf("%#v\n", contact)
    		}
    	}
    }
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    main.ContactInfo{Name:"John Smith", Email:"john@example.com", PlanInterest:"Enterprise", DemoRequested:true}
    ```

    SDKにマップ形式のスキーマを変換させるには、ベータAPIの`BetaJSONSchemaOutputFormat()`にスキーマを通してください。
  </Tab>

  <Tab title="Java">
    ```java
    import com.anthropic.core.JsonValue;
    import com.anthropic.models.messages.JsonOutputFormat;
    // ...
    import com.anthropic.models.messages.OutputConfig;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;

    void main() throws Exception {
        AnthropicClient client = AnthropicOkHttpClient.fromEnv();

        JsonOutputFormat.Schema schema = JsonOutputFormat.Schema.builder()
            .putAdditionalProperty("type", JsonValue.from("object"))
            .putAdditionalProperty("properties", JsonValue.from(Map.of(
                "name", Map.of("type", "string"),
                "email", Map.of("type", "string"),
                "plan_interest", Map.of("type", "string"))))
            .putAdditionalProperty("required", JsonValue.from(
                List.of("name", "email", "plan_interest")))
            .putAdditionalProperty("additionalProperties", JsonValue.from(false))
            .build();

        OutputConfig outputConfig = OutputConfig.builder()
            .format(JsonOutputFormat.builder().schema(schema).build())
            .build();

        MessageCreateParams createParams = MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_5_5)
            .maxTokens(1024)
            .outputConfig(outputConfig)
            .addUserMessage(
                "John Smith (john@example.com) is interested in our Enterprise plan.")
            .build();

        String json = client.messages().create(createParams).content().stream()
            .flatMap(contentBlock -> contentBlock.text().stream())
            .findFirst()
            .orElseThrow()
            .text();

        JsonNode contact = new ObjectMapper().readTree(json);
        IO.println(contact);
    }
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name":"John Smith","email":"john@example.com","plan_interest":"Enterprise"}
    ```

    配列と説明を含むネストされたスキーマを構築する、より詳細な例については、SDKリポジトリの[`StructuredOutputsRawExample.java`](https://github.com/anthropics/anthropic-sdk-java/blob/main/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsRawExample.java)を参照してください。
  </Tab>

  <Tab title="PHP">
    ```php
    use Anthropic\Messages\OutputConfig;
    use Anthropic\Messages\JSONOutputFormat;

    $client = new Client();

    $message = $client->messages->create(
        maxTokens: 1024,
        messages: [
            [
                'role' => 'user',
                'content' => 'Extract the key information from this email: '
                    . 'John Smith (john@example.com) is interested in our Enterprise plan.',
            ],
        ],
        model: 'claude-opus-5-5',
        outputConfig: OutputConfig::with(format: JSONOutputFormat::with(schema: [
            'type' => 'object',
            'properties' => [
                'name' => ['type' => 'string'],
                'email' => ['type' => 'string'],
                'plan_interest' => ['type' => 'string'],
            ],
            'required' => ['name', 'email', 'plan_interest'],
            'additionalProperties' => false,
        ])),
    );

    $textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
    $contact = json_decode($textBlock->text, associative: true);
    var_dump($contact);
    ```

    スキーマを連想配列として`OutputConfig::with()`に渡し、応答を`json_decode()`でデコードします。

    上記の例の出力は次のとおりです。

    ```text Output wrap
    array(3) {
      ["name"]=>
      string(10) "John Smith"
      ["email"]=>
      string(16) "john@example.com"
      ["plan_interest"]=>
      string(10) "Enterprise"
    }
    ```
  </Tab>

  <Tab title="Ruby">
    ```ruby
    client = Anthropic::Client.new

    response = client.messages.create(
      model: "claude-opus-5-5",
      max_tokens: 1024,
      messages: [
        {
          role: "user",
          content: "Extract the key information from this email: " \
            "John Smith (john@example.com) is interested in our Enterprise plan " \
            "and wants to schedule a demo for next Tuesday at 2pm."
        }
      ],
      output_config: {
        format: {
          type: "json_schema",
          schema: {
            type: "object",
            properties: {
              name: { type: "string" },
              email: { type: "string" },
              plan_interest: { type: "string" },
              demo_requested: { type: "boolean" }
            },
            required: ["name", "email", "plan_interest", "demo_requested"],
            additionalProperties: false
          }
        }
      }
    )

    text = response.content.find { it.type == :text }.text
    contact = JSON.parse(text)
    p contact
    ```

    上記の例の出力は次のとおりです。

    ```text Output wrap
    {"name" => "John Smith", "email" => "john@example.com", "plan_interest" => "Enterprise", "demo_requested" => true}
    ```
  </Tab>
</Tabs>

## 一般的なユースケース

<AccordionGroup>
  <Accordion title="データ抽出">
    非構造化テキストから構造化データを抽出します。

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 4096,
          "messages": [
            {
              "role": "user",
              "content": "Extract invoice data from: Invoice #12345, Date: 2024-01-15, Total: $500.00"
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "invoice_number": {"type": "string"},
                  "date": {"type": "string"},
                  "total_amount": {"type": "number"},
                  "line_items": {
                    "type": "array",
                    "items": {"type": "object", "additionalProperties": false}
                  },
                  "customer_name": {"type": "string"}
                },
                "required": ["invoice_number", "date", "total_amount", "line_items", "customer_name"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text|@fromstr' \
        --format jsonl <<'YAML'
      model: claude-opus-5-5
      max_tokens: 4096
      messages:
        - role: user
          content: "Extract invoice data from: Invoice #12345, Date: 2024-01-15, Total: $500.00"
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              invoice_number: {type: string}
              date: {type: string}
              total_amount: {type: number}
              line_items:
                type: array
                items: {type: object, additionalProperties: false}
              customer_name: {type: string}
            required: [invoice_number, date, total_amount, line_items, customer_name]
            additionalProperties: false
      YAML
      ```

      ```python Python
      from pydantic import BaseModel


      class Invoice(BaseModel):
          invoice_number: str
          date: str
          total_amount: float
          line_items: list[dict]
          customer_name: str


      client = anthropic.Anthropic()
      invoice_text = "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=4096,
          output_format=Invoice,
          messages=[
              {"role": "user", "content": f"Extract invoice data from: {invoice_text}"}
          ],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const InvoiceSchema = z.object({
        invoice_number: z.string(),
        date: z.string(),
        total_amount: z.number(),
        line_items: z.array(z.record(z.string(), z.any())),
        customer_name: z.string()
      });

      const invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";
      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 4096,
        output_config: { format: zodOutputFormat(InvoiceSchema) },
        messages: [{ role: "user", content: `Extract invoice data from: ${invoiceText}` }]
      });
      console.log(response.parsed_output);
      ```

      ```csharp C#
      AnthropicClient client = new();

      string invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 4096,
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          invoice_number = new { type = "string" },
                          date = new { type = "string" },
                          total_amount = new { type = "number" },
                          line_items = new
                          {
                              type = "array",
                              items = new
                              {
                                  type = "object",
                                  additionalProperties = false,
                              },
                          },
                          customer_name = new { type = "string" },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "invoice_number", "date", "total_amount", "line_items", "customer_name" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
          Messages = [new() { Role = Role.User, Content = $"Extract invoice data from: {invoiceText}" }]
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      client := anthropic.NewClient()

      invoiceText := "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      schema := map[string]any{
      	"type":                 "object",
      	"additionalProperties": false,
      	"properties": map[string]any{
      		"invoice_number": map[string]any{"type": "string"},
      		"date":           map[string]any{"type": "string"},
      		"total_amount":   map[string]any{"type": "number"},
      		"line_items": map[string]any{
      			"type": "array",
      			"items": map[string]any{
      				"type":                 "object",
      				"additionalProperties": false,
      				"properties": map[string]any{
      					"description": map[string]any{"type": "string"},
      					"quantity":    map[string]any{"type": "number"},
      					"unit_price":  map[string]any{"type": "number"},
      				},
      				"required": []string{"description", "quantity", "unit_price"},
      			},
      		},
      		"customer_name": map[string]any{"type": "string"},
      	},
      	"required": []string{"invoice_number", "date", "total_amount", "line_items", "customer_name"},
      }

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 4096,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: schema,
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock(fmt.Sprintf("Extract invoice data from: %s", invoiceText))),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		fmt.Println(variant.Text)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class LineItem {
          @JsonProperty("description")
          public String description;

          @JsonProperty("quantity")
          public int quantity;

          @JsonProperty("unit_price")
          public double unitPrice;
      }

      static class Invoice {
          @JsonProperty("invoice_number")
          public String invoiceNumber;

          @JsonProperty("date")
          public String date;

          @JsonProperty("total_amount")
          public double totalAmount;

          @JsonProperty("line_items")
          public List<LineItem> lineItems;

          @JsonProperty("customer_name")
          public String customerName;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          String invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

          StructuredMessageCreateParams<Invoice> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(4096L)
              .outputConfig(Invoice.class)
              .addUserMessage("Extract invoice data from: " + invoiceText)
              .build();

          StructuredMessage<Invoice> response = client.messages().create(params);
          Invoice invoice = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(invoice.invoiceNumber + ": $" + invoice.totalAmount);
      }
      ```

      ```php PHP
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Invoice implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $invoice_number;
          public string $date;
          public float $total_amount;
          public array $line_items;
          public string $customer_name;
      }

      $invoiceText = "Invoice #12345, Date: 2024-01-15, Total: $500.00";

      $message = $client->messages->create(
          maxTokens: 4096,
          messages: [
              ['role' => 'user', 'content' => "Extract invoice data from: $invoiceText"]
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => Invoice::class],
      );

      $invoice = $message->parsedOutput();
      if ($invoice instanceof Invoice) {
          echo "Invoice {$invoice->invoice_number}: \${$invoice->total_amount}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class LineItem < Anthropic::BaseModel
        required :description, String
        required :amount, Float
      end

      class Invoice < Anthropic::BaseModel
        required :invoice_number, String
        required :date, String
        required :total_amount, Float
        required :line_items, Anthropic::ArrayOf[LineItem]
        required :customer_name, String
      end

      invoice_text = "Invoice #12345, Date: 2024-01-15, Total: $500.00"

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 4096,
        output_config: {format: Invoice},
        messages: [
          {role: "user", content: "Extract invoice data from: #{invoice_text}"}
        ]
      )

      invoice = message.parsed_output
      puts "Invoice #{invoice.invoice_number}: $#{invoice.total_amount}"
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="分類">
    構造化されたカテゴリでコンテンツを分類します。

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 1024,
          "messages": [
            {
              "role": "user",
              "content": "Classify this feedback: Great product, fast shipping!"
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "category": {"type": "string"},
                  "confidence": {"type": "number"},
                  "tags": {"type": "array", "items": {"type": "string"}},
                  "sentiment": {"type": "string"}
                },
                "required": ["category", "confidence", "tags", "sentiment"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text|@fromstr' \
        --format jsonl <<'YAML'
      model: claude-opus-5-5
      max_tokens: 1024
      messages:
        - role: user
          content: "Classify this feedback: Great product, fast shipping!"
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              category:
                type: string
              confidence:
                type: number
              tags:
                type: array
                items:
                  type: string
              sentiment:
                type: string
            required:
              - category
              - confidence
              - tags
              - sentiment
            additionalProperties: false
      YAML
      ```

      ```python Python
      from pydantic import BaseModel

      client = Anthropic()


      class Classification(BaseModel):
          category: str
          confidence: float
          tags: list[str]
          sentiment: str


      feedback_text = "Great product, but the delivery was slow."
      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=1024,
          output_format=Classification,
          messages=[{"role": "user", "content": f"Classify this feedback: {feedback_text}"}],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const ClassificationSchema = z.object({
        category: z.string(),
        confidence: z.number(),
        tags: z.array(z.string()),
        sentiment: z.string()
      });

      const feedbackText = "Great product, but the delivery was slow.";
      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: { format: zodOutputFormat(ClassificationSchema) },
        messages: [{ role: "user", content: `Classify this feedback: ${feedbackText}` }]
      });

      console.log(response.parsed_output);
      ```

      ```csharp C#
      string feedbackText = "Great product, fast shipping!";

      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = $"Classify this feedback: {feedbackText}" }],
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          category = new { type = "string" },
                          confidence = new { type = "number" },
                          tags = new { type = "array", items = new { type = "string" } },
                          sentiment = new { type = "string" },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "category", "confidence", "tags", "sentiment" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      feedbackText := "Great product, fast shipping!"

      schema := map[string]any{
      	"type": "object",
      	"properties": map[string]any{
      		"category":   map[string]any{"type": "string"},
      		"confidence": map[string]any{"type": "number"},
      		"tags":       map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
      		"sentiment":  map[string]any{"type": "string"},
      	},
      	"required":             []string{"category", "confidence", "tags", "sentiment"},
      	"additionalProperties": false,
      }

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 1024,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: schema,
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock(fmt.Sprintf("Classify this feedback: %s", feedbackText))),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		var result map[string]any
      		json.Unmarshal([]byte(variant.Text), &result)
      		fmt.Println(result)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class Classification {
          @JsonProperty("category")
          public String category;

          @JsonProperty("confidence")
          public double confidence;

          @JsonProperty("tags")
          public List<String> tags;

          @JsonProperty("sentiment")
          public String sentiment;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          String feedbackText = "Great product, fast shipping!";

          StructuredMessageCreateParams<Classification> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .outputConfig(Classification.class)
              .addUserMessage("Classify this feedback: " + feedbackText)
              .build();

          StructuredMessage<Classification> response = client.messages().create(params);
          Classification result = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(result.category + " (" + result.confidence + ")");
      }
      ```

      ```php PHP
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Classification implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $category;
          public float $confidence;
          public array $tags;
          public string $sentiment;
      }

      $feedbackText = "Great product, fast shipping!";

      $message = $client->messages->create(
          maxTokens: 1024,
          messages: [
              ['role' => 'user', 'content' => "Classify this feedback: {$feedbackText}"]
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => Classification::class],
      );

      $result = $message->parsedOutput();
      if ($result instanceof Classification) {
          echo "{$result->category} ({$result->confidence}): {$result->sentiment}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class Classification < Anthropic::BaseModel
        required :category, String
        required :confidence, Float
        required :tags, Anthropic::ArrayOf[String]
        required :sentiment, String
      end

      feedback_text = "Great product, fast shipping!"

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: {format: Classification},
        messages: [
          {role: "user", content: "Classify this feedback: #{feedback_text}"}
        ]
      )
      puts message.parsed_output
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="API応答のフォーマット">
    APIですぐに使える応答を生成します。

    <CodeGroup>
      ```bash cURL
      curl https://api.anthropic.com/v1/messages \
        -H "content-type: application/json" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 1024,
          "messages": [
            {
              "role": "user",
              "content": "Process this request: ..."
            }
          ],
          "output_config": {
            "format": {
              "type": "json_schema",
              "schema": {
                "type": "object",
                "properties": {
                  "status": {"type": "string"},
                  "data": {"type": "object", "additionalProperties": false},
                  "errors": {
                    "type": "array",
                    "items": {"type": "object", "additionalProperties": false}
                  },
                  "metadata": {"type": "object", "additionalProperties": false}
                },
                "required": ["status", "data", "metadata"],
                "additionalProperties": false
              }
            }
          }
        }'
      ```

      ```bash CLI
      ant messages create \
        --transform 'content.#(type=="text").text' \
        --raw-output <<'YAML'
      model: claude-opus-5-5
      max_tokens: 1024
      output_config:
        format:
          type: json_schema
          schema:
            type: object
            properties:
              status:
                type: string
              data:
                type: object
                additionalProperties: false
              errors:
                type: array
                items:
                  type: object
                  additionalProperties: false
              metadata:
                type: object
                additionalProperties: false
            required:
              - status
              - data
              - metadata
            additionalProperties: false
      messages:
        - role: user
          content: "Process this request: ..."
      YAML
      ```

      ```python Python
      from pydantic import BaseModel

      client = Anthropic()


      class APIResponse(BaseModel):
          status: str
          data: dict
          errors: list[dict] | None
          metadata: dict


      response = client.messages.parse(
          model="claude-opus-5-5",
          max_tokens=1024,
          output_format=APIResponse,
          messages=[{"role": "user", "content": "Process this request: ..."}],
      )

      print(response.parsed_output)
      ```

      ```typescript TypeScript
      import { z } from "zod";
      import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

      const client = new Anthropic();

      const APIResponseSchema = z.object({
        status: z.string(),
        data: z.record(z.string(), z.any()),
        errors: z.array(z.record(z.string(), z.any())).optional(),
        metadata: z.record(z.string(), z.any())
      });

      const response = await client.messages.parse({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: { format: zodOutputFormat(APIResponseSchema) },
        messages: [{ role: "user", content: "Process this request..." }]
      });

      console.log(response.parsed_output);
      ```

      ```csharp C#
      var parameters = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = "Process this request: ..." }],
          OutputConfig = new OutputConfig
          {
              Format = new JsonOutputFormat
              {
                  Schema = new Dictionary<string, JsonElement>
                  {
                      ["type"] = JsonSerializer.SerializeToElement("object"),
                      ["properties"] = JsonSerializer.SerializeToElement(new
                      {
                          status = new { type = "string" },
                          data = new { type = "object", additionalProperties = false },
                          errors = new
                          {
                              type = "array",
                              items = new { type = "object", additionalProperties = false },
                          },
                          metadata = new { type = "object", additionalProperties = false },
                      }),
                      ["required"] = JsonSerializer.SerializeToElement(new[] { "status", "data", "metadata" }),
                      ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
                  },
              },
          },
      };

      var message = await client.Messages.Create(parameters);
      Console.WriteLine(message);
      ```

      ```go Go
      client := anthropic.NewClient()

      response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 1024,
      	OutputConfig: anthropic.OutputConfigParam{
      		Format: anthropic.JSONOutputFormatParam{
      			Schema: map[string]any{
      				"type":                 "object",
      				"additionalProperties": false,
      				"properties": map[string]any{
      					"status": map[string]any{
      						"type": "string",
      					},
      					"data": map[string]any{
      						"type":                 "object",
      						"additionalProperties": false,
      					},
      					"errors": map[string]any{
      						"type": "array",
      						"items": map[string]any{
      							"type":                 "object",
      							"additionalProperties": false,
      						},
      					},
      					"metadata": map[string]any{
      						"type":                 "object",
      						"additionalProperties": false,
      					},
      				},
      				"required": []string{"status", "data", "metadata"},
      			},
      		},
      	},
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock("Process this request: ...")),
      	},
      })
      if err != nil {
      	log.Fatal(err)
      }
      for _, block := range response.Content {
      	switch variant := block.AsAny().(type) {
      	case anthropic.TextBlock:
      		fmt.Println(variant.Text)
      	}
      }
      ```

      ```java Java
      import com.fasterxml.jackson.annotation.JsonProperty;

      static class APIData {
          @JsonProperty("message")
          public String message;

          @JsonProperty("resource_id")
          public String resourceId;
      }

      static class APIError {
          @JsonProperty("code")
          public String code;

          @JsonProperty("message")
          public String message;
      }

      static class APIMetadata {
          @JsonProperty("request_id")
          public String requestId;

          @JsonProperty("timestamp")
          public String timestamp;
      }

      static class APIResponse {
          @JsonProperty("status")
          public String status;

          @JsonProperty("data")
          public APIData data;

          @JsonProperty("errors")
          public List<APIError> errors;

          @JsonProperty("metadata")
          public APIMetadata metadata;
      }

      void main() {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          StructuredMessageCreateParams<APIResponse> params = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024L)
              .outputConfig(APIResponse.class)
              .addUserMessage("Process this request: ...")
              .build();

          StructuredMessage<APIResponse> response = client.messages().create(params);
          APIResponse result = response.content().stream()
              .flatMap(block -> block.text().stream())
              .findFirst().orElseThrow().text();
          IO.println(result.status);
      }
      ```

      ```php PHP
      use Anthropic\Lib\Attributes\Constrained;
      use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
      use Anthropic\Lib\Contracts\StructuredOutputModel;

      $client = new Client();

      class Payload implements StructuredOutputModel { use StructuredOutputModelTrait; public string $message; }

      class APIError implements StructuredOutputModel { use StructuredOutputModelTrait; public string $code; public string $detail; }

      class Metadata implements StructuredOutputModel { use StructuredOutputModelTrait; public string $request_id; }

      class APIResponse implements StructuredOutputModel
      {
          use StructuredOutputModelTrait;

          public string $status;
          public Payload $data;
          #[Constrained(itemClass: APIError::class)]
          public ?array $errors;
          public Metadata $metadata;
      }

      $message = $client->messages->create(
          maxTokens: 1024,
          messages: [
              ['role' => 'user', 'content' => 'Process this request: ...']
          ],
          model: 'claude-opus-5-5',
          outputConfig: ['format' => APIResponse::class],
      );

      $result = $message->parsedOutput();
      if ($result instanceof APIResponse) {
          echo "{$result->status}: {$result->data->message}\n";
      }
      ```

      ```ruby Ruby
      client = Anthropic::Client.new

      class Payload < Anthropic::BaseModel
        required :message, String
      end

      class APIError < Anthropic::BaseModel
        required :code, String
        required :detail, String
      end

      class Metadata < Anthropic::BaseModel
        required :request_id, String
      end

      class APIResponse < Anthropic::BaseModel
        required :status, String
        required :data, Payload
        optional :errors, Anthropic::ArrayOf[APIError]
        required :metadata, Metadata
      end

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        output_config: {format: APIResponse},
        messages: [
          {role: "user", content: "Process this request: ..."}
        ]
      )
      puts message.parsed_output
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## 厳密なツール使用

文法制約付きサンプリングによってツール入力にJSON Schema準拠を強制するには、[厳密なツール使用](https://platform.claude.com/docs/ja/agents-and-tools/tool-use/strict-tool-use)を参照してください。

### 両方の機能を併用する

JSON出力と厳密なツール使用は異なる問題を解決し、連携して動作します。

* **JSON出力**はClaudeの応答形式（Claudeが何を言うか）を制御します
* **厳密なツール使用**はツールパラメータ（Claudeが関数をどのように呼び出すか）を検証します

組み合わせると、Claudeは有効性が保証されたパラメータでツールを呼び出し、かつ構造化されたJSON応答を返すことができます。これは、信頼性の高いツール呼び出しと構造化された最終出力の両方が必要なエージェントワークフローに役立ちます。

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": "Help me plan a trip to Paris departing May 15, 2026"
        }
      ],
      "output_config": {
        "format": {
          "type": "json_schema",
          "schema": {
            "type": "object",
            "properties": {
              "summary": {"type": "string"},
              "next_steps": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["summary", "next_steps"],
            "additionalProperties": false
          }
        }
      },
      "tools": [
        {
          "name": "search_flights",
          "strict": true,
          "input_schema": {
            "type": "object",
            "properties": {
              "destination": {"type": "string"},
              "date": {"type": "string", "format": "date"}
            },
            "required": ["destination", "date"],
            "additionalProperties": false
          }
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content: Help me plan a trip to Paris departing May 15, 2026
  # JSON出力: 構造化されたレスポンス形式
  output_config:
    format:
      type: json_schema
      schema:
        type: object
        properties:
          summary:
            type: string
          next_steps:
            type: array
            items:
              type: string
        required: [summary, next_steps]
        additionalProperties: false
  # 厳格なツール使用: ツールパラメータが保証されます
  tools:
    - name: search_flights
      strict: true
      input_schema:
        type: object
        properties:
          destination:
            type: string
          date:
            type: string
            format: date
        required: [destination, date]
        additionalProperties: false
  YAML
  ```

  ```python Python
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": "Help me plan a trip to Paris departing May 15, 2026",
          }
      ],
      # JSON出力：構造化されたレスポンス形式
      output_config={
          "format": {
              "type": "json_schema",
              "schema": {
                  "type": "object",
                  "properties": {
                      "summary": {"type": "string"},
                      "next_steps": {"type": "array", "items": {"type": "string"}},
                  },
                  "required": ["summary", "next_steps"],
                  "additionalProperties": False,
              },
          }
      },
      # 厳格なツール使用：ツールパラメータを保証
      tools=[
          {
              "name": "search_flights",
              "strict": True,
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "destination": {"type": "string"},
                      "date": {"type": "string", "format": "date"},
                  },
                  "required": ["destination", "date"],
                  "additionalProperties": False,
              },
          }
      ],
  )

  print(response)
  ```

  ```typescript TypeScript
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Help me plan a trip to Paris departing May 15, 2026" }],
    // JSON outputs（JSON出力）：構造化されたレスポンス形式
    output_config: {
      format: {
        type: "json_schema",
        schema: {
          type: "object",
          properties: {
            summary: { type: "string" },
            next_steps: { type: "array", items: { type: "string" } }
          },
          required: ["summary", "next_steps"],
          additionalProperties: false
        }
      }
    },
    // Strict tool use（厳格なツール使用）：ツールパラメータが保証されます
    tools: [
      {
        name: "search_flights",
        description: "Search for available flights to a destination on a specific date",
        strict: true,
        input_schema: {
          type: "object",
          properties: {
            destination: { type: "string" },
            date: { type: "string", format: "date" }
          },
          required: ["destination", "date"],
          additionalProperties: false
        }
      }
    ]
  });

  // Claudeは最初にツールを呼び出す（tool_use）か、JSON（テキスト）で応答する場合があります
  console.log("Stop reason:", response.stop_reason);
  for (const block of response.content) {
    switch (block.type) {
      case "tool_use":
        console.log(`Tool call: ${block.name}(${JSON.stringify(block.input)})`);
        break;
      case "text":
        console.log("Response:", block.text);
        break;
    }
  }
  ```

  ```csharp C#
  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Help me plan a trip to Paris departing May 15, 2026" }],
      // JSON出力：構造化されたレスポンス形式
      OutputConfig = new OutputConfig
      {
          Format = new JsonOutputFormat
          {
              Schema = new Dictionary<string, JsonElement>
              {
                  ["type"] = JsonSerializer.SerializeToElement("object"),
                  ["properties"] = JsonSerializer.SerializeToElement(new
                  {
                      summary = new { type = "string" },
                      next_steps = new { type = "array", items = new { type = "string" } },
                  }),
                  ["required"] = JsonSerializer.SerializeToElement(new[] { "summary", "next_steps" }),
                  ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
              },
          },
      },
      // 厳格なツール使用：ツールパラメータを保証
      Tools =
      [
          new Tool
          {
              Name = "search_flights",
              Strict = true,
              InputSchema = new InputSchema(new Dictionary<string, JsonElement>
              {
                  ["properties"] = JsonSerializer.SerializeToElement(new Dictionary<string, object>
                  {
                      ["destination"] = new { type = "string" },
                      ["date"] = new { type = "string", format = "date" },
                  }),
                  ["required"] = JsonSerializer.SerializeToElement(new[] { "destination", "date" }),
                  ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
              }),
          }
      ],
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Help me plan a trip to Paris departing May 15, 2026")),
  	},
  	// JSON outputs（JSON出力）：構造化されたレスポンス形式
  	OutputConfig: anthropic.OutputConfigParam{
  		Format: anthropic.JSONOutputFormatParam{
  			Schema: map[string]any{
  				"type":                 "object",
  				"additionalProperties": false,
  				"properties": map[string]any{
  					"summary":    map[string]any{"type": "string"},
  					"next_steps": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
  				},
  				"required": []string{"summary", "next_steps"},
  			},
  		},
  	},
  	// Strict tool use（厳格なツール使用）：ツールパラメータを保証します
  	Tools: []anthropic.ToolUnionParam{
  		{OfTool: &anthropic.ToolParam{
  			Name:   "search_flights",
  			Strict: anthropic.Bool(true),
  			InputSchema: anthropic.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"destination": map[string]any{"type": "string"},
  					"date":        map[string]any{"type": "string", "format": "date"},
  				},
  				Required: []string{"destination", "date"},
  				ExtraFields: map[string]any{
  					"additionalProperties": false,
  				},
  			}}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.Content)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  // JSON outputs（JSON出力）：構造化されたレスポンス形式
  JsonOutputFormat.Schema outputSchema = JsonOutputFormat.Schema.builder()
      .putAdditionalProperty("type", JsonValue.from("object"))
      .putAdditionalProperty("properties", JsonValue.from(Map.of(
          "summary", Map.of("type", "string"),
          "next_steps", Map.of("type", "array", "items", Map.of("type", "string"))
      )))
      .putAdditionalProperty("required", JsonValue.from(List.of("summary", "next_steps")))
      .putAdditionalProperty("additionalProperties", JsonValue.from(false))
      .build();

  // Strict tool use（厳格なツール使用）：ツールパラメータを保証します
  InputSchema toolSchema = InputSchema.builder()
      .properties(JsonValue.from(Map.of(
          "destination", Map.of("type", "string"),
          "date", Map.of("type", "string", "format", "date")
      )))
      .putAdditionalProperty("required", JsonValue.from(List.of("destination", "date")))
      .putAdditionalProperty("additionalProperties", JsonValue.from(false))
      .build();

  MessageCreateParams params = MessageCreateParams.builder()
      .model(Model.CLAUDE_OPUS_5_5)
      .maxTokens(1024L)
      .addUserMessage("Help me plan a trip to Paris departing May 15, 2026")
      .outputConfig(OutputConfig.builder()
          .format(JsonOutputFormat.builder().schema(outputSchema).build())
          .build())
      .addTool(Tool.builder()
          .name("search_flights")
          .description("Search for available flights to a destination on a specific date")
          .strict(true)
          .inputSchema(toolSchema)
          .build())
      .build();

  Message response = client.messages().create(params);
  IO.println(response);
  ```

  ```php PHP
  use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
  use Anthropic\Lib\Contracts\StructuredOutputModel;
  use Anthropic\Messages\ToolUseBlock;

  $client = new Client();

  class TripPlan implements StructuredOutputModel
  {
      use StructuredOutputModelTrait;

      public string $summary;
      public array $next_steps;
  }

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          ['role' => 'user', 'content' => 'Help me plan a trip to Paris departing May 15, 2026']
      ],
      model: 'claude-opus-5-5',
      // JSON 出力：構造化されたレスポンス形式
      outputConfig: ['format' => TripPlan::class],
      // Strict tool use（厳格なツール使用）：ツールパラメータを保証
      tools: [
          [
              'name' => 'search_flights',
              'strict' => true,
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'destination' => ['type' => 'string'],
                      'date' => ['type' => 'string', 'format' => 'date']
                  ],
                  'required' => ['destination', 'date'],
                  'additionalProperties' => false
              ]
          ]
      ],
  );

  // Claude はまずツールを呼び出す（tool_use）か、JSON で応答（text）する場合があります
  $plan = $message->parsedOutput();
  if ($plan instanceof TripPlan) {
      echo $plan->summary, "\n";
  } elseif ($toolUse = array_find($message->content, fn($block) => $block instanceof ToolUseBlock)) {
      echo "Tool call: {$toolUse->name}(", json_encode($toolUse->input), ")\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [
      {role: "user", content: "Help me plan a trip to Paris departing May 15, 2026"}
    ],
    # JSON出力：構造化されたレスポンス形式
    output_config: {
      format: {
        type: :json_schema,
        schema: {
          type: "object",
          properties: {
            summary: {type: "string"},
            next_steps: {type: "array", items: {type: "string"}}
          },
          required: ["summary", "next_steps"],
          additionalProperties: false
        }
      }
    },
    # 厳格なツール使用：ツールパラメータを保証
    tools: [
      {
        name: "search_flights",
        strict: true,
        input_schema: {
          type: "object",
          properties: {
            destination: {type: "string"},
            date: {type: "string", format: "date"}
          },
          required: ["destination", "date"],
          additionalProperties: false
        }
      }
    ]
  )
  puts message
  ```
</CodeGroup>

## 重要な考慮事項

### 文法のコンパイルとキャッシング

構造化出力は、コンパイルされた文法アーティファクトによる制約付きサンプリングを使用します。これにより、注意すべきいくつかのパフォーマンス特性が生じます。

* **初回リクエストのレイテンシ：** 特定のスキーマを初めて使用する際、文法のコンパイル中に追加の「latency」（レイテンシ）が発生します

* **自動キャッシング：** コンパイルされた文法は最後の使用から24時間キャッシュされるため、後続のリクエストは大幅に高速になります

* **キャッシュの無効化：** 次のものを変更するとキャッシュが無効化されます。

  * JSONスキーマの構造
  * リクエスト内のツールのセット（構造化出力とツール使用の両方を使用している場合）
  * `name`または`description`フィールドのみを変更してもキャッシュは無効化されません

### プロンプトの変更とトークンコスト

構造化出力を使用する場合、Claudeは期待される出力形式を説明する追加のシステムプロンプトを自動的に受け取ります。これは次のことを意味します。

* 入力トークン数がわずかに増加します
* 挿入されたプロンプトは、他のシステムプロンプトと同様にトークンを消費します
* `output_config.format`パラメータを変更すると、その会話スレッドの[プロンプトキャッシング](https://platform.claude.com/docs/ja/build-with-claude/prompt-caching)が無効化されます

### JSON Schemaの制限

構造化出力は標準のJSON Schemaをサポートしますが、いくつかの制限があります。JSON出力と厳密なツール使用の両方がこれらの制限を共有します。

<Accordion title="サポートされている機能">
  * すべての基本型：object、array、string、integer、number、boolean、null
  * `enum`（文字列、数値、ブール値、またはnullのみ。複合型は不可）。大文字・小文字に関する注意点については、[無効な出力](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#invalid-outputs)を参照してください。
  * `const`
  * `anyOf`と`allOf`（制限あり。`$ref`を含む`allOf`はサポートされません）
  * `$ref`、`$def`、および`definitions`（外部`$ref`はサポートされません）
  * サポートされているすべての型の`default`プロパティ
  * `required`と`additionalProperties`（オブジェクトでは`false`に設定する必要があります）
  * 文字列フォーマット：`date-time`、`time`、`date`、`duration`、`email`、`hostname`、`uri`、`ipv4`、`ipv6`、`uuid`
  * 配列の`minItems`（値0と1のみサポート）
</Accordion>

<Accordion title="サポートされていない機能">
  * 再帰的スキーマ
  * enum内の複雑な型
  * 外部`$ref`（例：`'$ref': 'http://...'`）
  * 数値制約（`minimum`、`maximum`、`multipleOf`など）
  * 文字列制約（`minLength`、`maxLength`）
  * `minItems`の0または1以外の配列制約
  * `false`以外に設定された`additionalProperties`

  サポートされていない機能を使用すると、詳細を含む400エラーが返されます。
</Accordion>

<Accordion title="パターンのサポート（正規表現）">
  **サポートされている正規表現機能：**

  * 完全一致（`^...$`）と部分一致
  * 量指定子：`*`、`+`、`?`、単純な`{n,m}`のケース
  * 文字クラス：`[]`、`.`、`\d`、`\w`、`\s`
  * グループ：`(...)`

  **サポートされていないもの：**

  * グループへの後方参照（例：`\1`、`\2`）
  * 先読み/後読みアサーション（例：`(?=...)`、`(?!...)`）
  * 単語境界：`\b`、`\B`
  * 大きな範囲を持つ複雑な`{n,m}`量指定子

  単純な正規表現パターンは問題なく動作します。複雑なパターンは400エラーになる可能性があります。
</Accordion>

<Tip>
  SDKヘルパーは、[APIでサポートされていない制約](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#json-schema-limitations)を含むスキーマを変換できます。[SDKによる変換の仕組み](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#how-sdk-transformation-works)を参照してください。
</Tip>

### プロパティの順序

構造化出力を使用する場合、オブジェクト内のプロパティはスキーマで定義された順序を維持しますが、1つ重要な注意点があります。**必須プロパティが最初に表示され、その後にオプションプロパティが続きます**。

例えば、次のスキーマの場合：

```json
{
  "type": "object",
  "properties": {
    "notes": { "type": "string" },
    "name": { "type": "string" },
    "email": { "type": "string" },
    "age": { "type": "integer" }
  },
  "required": ["name", "email"],
  "additionalProperties": false
}
```

出力ではプロパティが次の順序になります。

1. `name`（必須、スキーマ順）
2. `email`（必須、スキーマ順）
3. `notes`（オプション、スキーマ順）
4. `age`（オプション、スキーマ順）

つまり、出力は次のようになる可能性があります。

```json
{
  "name": "John Smith",
  "email": "john@example.com",
  "notes": "Interested in enterprise plan",
  "age": 35
}
```

出力内のプロパティの順序がアプリケーションにとって重要な場合は、すべてのプロパティを必須としてマークするか、解析ロジックでこの並べ替えを考慮してください。

### 無効な出力

構造化出力はほとんどの場合スキーマ準拠を保証しますが、出力がスキーマに一致しない可能性があるシナリオがあります。

**拒否**（`stop_reason: "refusal"`）

Claudeは構造化出力を使用している場合でも、安全性と有用性の特性を維持します。Claudeが安全上の理由でリクエストを拒否した場合：

* 応答は`stop_reason: "refusal"`になります
* 200ステータスコードが返されます
* 生成されたトークンに対して課金されます
* 拒否メッセージがスキーマ制約よりも優先されるため、出力がスキーマに一致しない可能性があります

モデルの思考やステップバイステップの推論を求めるプロパティは、`reasoning_extraction`による拒否につながる可能性があります。代わりに短い説明を求めてください。[推論を思考ブロック内に保つ](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks)を参照してください。

**トークン制限に到達**（`stop_reason: "max_tokens"`）

`max_tokens`制限に達したために応答が途中で切れた場合：

* 応答は`stop_reason: "max_tokens"`になります
* 出力が不完全でスキーマに一致しない可能性があります
* 完全な構造化出力を得るには、より大きな`max_tokens`値で再試行してください

**enum値の大文字小文字**

構造化出力は文字列の`enum`および`const`値の大文字小文字を保証しません。Claudeは、スキーマと大文字小文字のみが異なる値を返すことがあり、通常はスペースに続く単語の最初の文字で発生します。例えば、次のスキーマの場合：

```json
{
  "type": "string",
  "enum": ["Conversation Topic 1", "Conversation Topic 2", "Conversation topic 3"]
}
```

その正確な値がenumに含まれていなくても、出力に`"Conversation Topic 3"`（大文字の「T」）が含まれる可能性があります。応答はエラーも特別な`stop_reason`もなく正常に完了します。これはJSON出力と厳密なツール使用の両方に当てはまります。enum値は大文字小文字を区別せずに比較し、大文字小文字のみが異なるenum値は避けてください。

### スキーマの複雑さの制限

構造化出力は、JSONスキーマをClaudeの出力を制約する文法にコンパイルすることで機能します。より複雑なスキーマはより大きな文法を生成し、コンパイルに時間がかかります。過度なコンパイル時間を防ぐため、APIはいくつかの複雑さの制限を適用します。

#### 明示的な制限

次の制限は、`output_config.format`または`strict: true`を含むすべてのリクエストに適用されます。

| 制限               | 値  | 説明                                                                                                             |
| ---------------- | -- | -------------------------------------------------------------------------------------------------------------- |
| リクエストあたりの厳密なツール数 | 20 | `strict: true`を持つツールの最大数。厳密でないツールはこの制限にカウントされません。                                                              |
| オプションパラメータ       | 24 | すべての厳密なツールスキーマとJSON出力スキーマにわたるオプションパラメータの合計。`required`に記載されていない各パラメータがこの制限にカウントされます。                            |
| ユニオン型を持つパラメータ    | 16 | すべての厳密なスキーマにわたって`anyOf`または型配列（例：`"type": ["string", "null"]`）を使用するパラメータの合計。これらは指数的なコンパイルコストを生むため、特にコストが高くなります。 |

<Note>
  これらの制限は、単一のリクエスト内のすべての厳密なスキーマの合計に適用されます。例えば、それぞれ6つのオプションパラメータを持つ4つの厳密なツールがある場合、個々のツールは複雑に見えなくても、24パラメータの制限に達します。
</Note>

#### 追加の内部制限

前述の表の明示的な制限に加えて、コンパイルされた文法のサイズに関する追加の内部制限があります。これらの制限が存在するのは、スキーマの複雑さが単一の次元に還元できないためです。オプションパラメータ、ユニオン型、ネストされたオブジェクト、ツールの数などの機能は相互に作用し、コンパイルされた文法を不釣り合いに大きくする可能性があります。

これらの制限を超えると、「Schema is too complex for compilation.」というメッセージを含む400エラーが返されます。これらのエラーは、前述の表の個々の制限がすべて満たされていても、スキーマの合計の複雑さが効率的にコンパイルできる範囲を超えていることを意味します。最後の安全策として、APIは**180秒のコンパイルタイムアウト**も適用します。すべての明示的なチェックを通過しても非常に大きなコンパイル済み文法を生成するスキーマは、このタイムアウトに達する可能性があります。

#### スキーマの複雑さを軽減するためのヒント

複雑さの制限に達している場合は、次の戦略を順番に試してください。

1. **重要なツールのみを厳密としてマークする。** 多くのツールがある場合は、スキーマ違反が実際に問題を引き起こすツールにのみ適用し、より単純なツールについてはClaudeの自然な準拠に頼ってください。

2. **オプションパラメータを減らす。** 可能な限りパラメータを`required`にしてください。各オプションパラメータは文法の状態空間の一部をおおよそ2倍にします。パラメータに常に妥当なデフォルト値がある場合は、必須にしてClaudeにそのデフォルト値を明示的に提供させることを検討してください。

3. **ネスト構造を簡素化する。** オプションフィールドを持つ深くネストされたオブジェクトは複雑さを増大させます。可能な限り構造をフラットにしてください。

4. **複数のリクエストに分割する。** 多くの厳密なツールがある場合は、それらを別々のリクエストやサブエージェントに分割することを検討してください。

有効なスキーマで問題が解決しない場合は、スキーマ定義を添えて[サポートにお問い合わせ](https://support.claude.com/en/articles/9015913-how-to-get-support)ください。

## ベータ版からの移行

`output_format`パラメータは`output_config.format`に移動し、ベータヘッダーは不要になりました。`output_format`パラメータは非推奨であり、将来削除される予定です。それでも使用する場合は、`structured-outputs-2025-11-13`ベータヘッダーを追加してください。ヘッダーがない場合、APIは400エラーを返します。

Python SDK（v1.0以降）は、`client.beta.messages.create()`または`count_tokens()`で`output_format={...}`を受け付けず、`TypeError`を発生させます。代わりに`output_config`を使用してください。更新されたAPIの形式については、[生のJSONスキーマの使用](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#using-a-raw-json-schema)を参照してください。

## データ保持

構造化出力を使用する場合、プロンプトと応答はZDRで処理されます。ただし、JSONスキーマ自体は最適化のために最後の使用から最大24時間一時的にキャッシュされます。プロンプトや応答のデータはAPI応答を超えて保持されません。

構造化出力はHIPAA適格ですが、**PHIをJSONスキーマ定義に含めてはなりません**。APIはJSONスキーマをメッセージコンテンツとは別にキャッシュされる文法にコンパイルし、これらのキャッシュされたスキーマはプロンプトや応答と同じPHI保護を受けません。スキーマのプロパティ名、`enum`値、`const`値、または`pattern`正規表現にPHIを含めないでください。PHIは、HIPAAの保護措置の下で保護されるメッセージコンテンツ（プロンプトと応答）にのみ含めるべきです。

すべての機能にわたるZDRおよびHIPAAの適格性については、[APIとデータ保持](https://platform.claude.com/docs/ja/manage-claude/api-and-data-retention)を参照してください。

## 機能の互換性

**併用可能：**

* **[バッチ処理](https://platform.claude.com/docs/ja/build-with-claude/batch-processing)：** 50%割引で構造化出力を大規模に処理します
* **[トークンカウント](https://platform.claude.com/docs/ja/build-with-claude/token-counting)：** コンパイルなしでトークンをカウントします
* **[ストリーミング](https://platform.claude.com/docs/ja/build-with-claude/streaming)：** 通常の応答と同様に構造化出力をストリーミングします
* **[併用](https://platform.claude.com/docs/ja/build-with-claude/structured-outputs#using-both-features-together)：** JSON出力（`output_config.format`）と厳密なツール使用（`strict: true`）を同じリクエスト内で併用できます

**互換性なし：**

* **[引用](https://platform.claude.com/docs/ja/build-with-claude/citations)：** 引用は引用ブロックをテキストと交互に配置する必要があり、これは厳密なJSONスキーマ制約と競合します。`output_config.format`で引用が有効になっている場合は400エラーが返されます。
* **メッセージのプリフィル：** JSON出力と互換性がありません

<Tip>
  **文法のスコープ：** 文法はClaudeの直接の出力にのみ適用され、ツール使用の呼び出し、ツール結果、または思考タグ（[思考](https://platform.claude.com/docs/ja/build-with-claude/thinking)を使用している場合）には適用されません。文法の状態はセクション間でリセットされるため、Claudeは自由に思考しながら、最終応答では構造化出力を生成できます。
</Tip>

## 次のステップ

<CardGroup cols={2}>
  <Card title="引用" icon="book-bookmark" href="https://platform.claude.com/docs/ja/build-with-claude/citations">
    提供されたドキュメントに関する質問に答える際に、Claudeに出典を引用させます。
  </Card>

  <Card title="厳密なツール使用" icon="check" href="https://platform.claude.com/docs/ja/agents-and-tools/tool-use/strict-tool-use">
    文法制約付きサンプリングによって、ClaudeのツールインプットにJSON Schema準拠を強制します。
  </Card>

  <Card title="Claudeでのツール使用" icon="wrench" href="https://platform.claude.com/docs/ja/agents-and-tools/tool-use/overview">
    Claudeを外部ツールやAPIに接続します。ツールがどこで実行され、エージェントループがどのように機能するかを学びます。
  </Card>

  <Card title="価格" icon="calculator" href="https://platform.claude.com/docs/ja/about-claude/pricing">
    モデルと機能に関するAnthropicの価格体系について学びます。
  </Card>
</CardGroup>
