0Pricing
Claude Architect · 课时

设计 JSON 模式

将输出塑造成您确切需要的形式。

设计 JSON 模式 是 CoddyKit 上的免费 Claude Architect 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Claude Architect 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Claude Architect 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Why Schema-Shaped Output

When you need Claude's answer in a precise structure, don't parse free text and hope. Pair tool_use with a JSON Schema: Claude fills a tool's input_schema and the API guarantees valid JSON with your required fields present.

This eliminates two whole classes of failure: syntax errors (missing commas, unescaped quotes) and missing fields. The schema IS the contract — design it well and downstream code never has to defend against malformed shapes.

The Tool Is the Schema

A structured-output "tool" doesn't have to call anything. It's just a named container whose input_schema describes the shape you want back. You define it, then read what Claude put in the tool call.

Give the tool a clear name and description — these still drive selection — but the real work is in the schema's properties and required list.

extract_invoice = {
    "name": "extract_invoice",
    "description": "Record the structured fields parsed from an invoice document.",
    "input_schema": {
        "type": "object",
        "properties": {
            "invoice_number": {"type": "string"},
            "total": {"type": "number"},
        },
        "required": ["invoice_number", "total"],
    },
}

Force the Structure with tool_choice

If you want guaranteed structured output, don't leave it to chance. Set tool_choice to force a tool call:

  • "auto" — model picks text or a tool
  • "any" — model MUST call some tool (guarantees structured output)
  • {"type":"tool","name":"X"} — force one specific tool

For single-schema extraction, forcing the exact tool by name is the cleanest path to a deterministic shape.

resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    tools=[extract_invoice],
    tool_choice={"type": "tool", "name": "extract_invoice"},
    messages=[{"role": "user", "content": invoice_text}],
)

Required Means Always Present

The single most important schema rule: mark a field required ONLY if it is always present in the source. Never require a field that may be absent.

Why? A required field forces the model to emit a value. If the data isn't there, Claude will fabricate one to satisfy the contract. Optional-but-absent is honest; required-but-missing breeds hallucination.

Optional Fields, Done Right

For fields that may or may not appear — a discount line, a secondary contact, a due date — leave them OUT of required. Describe them clearly so Claude only fills them when the data genuinely exists.

A good description tells the model the input format and the absence rule, so it omits rather than invents.

"properties": {
    "invoice_number": {"type": "string"},
    "total": {"type": "number"},
    "due_date": {
        "type": "string",
        "description": "ISO 8601 date (YYYY-MM-DD). Omit entirely if no due date is stated."
    },
},
"required": ["invoice_number", "total"]

Enums Constrain the Output

When a field has a fixed vocabulary — status, category, priority — use an enum. This collapses messy free text ("paid", "PAID", "settled") into one canonical value your code can switch on.

Enums also reduce hallucination: the model must choose from the listed set instead of inventing a label.

"status": {
    "type": "string",
    "enum": ["draft", "sent", "paid", "overdue", "void"],
    "description": "Current invoice status."
}

Designing Enums for Extensibility

Rigid enums break when reality grows a new case. The architect's pattern: add an "other" value to the enum AND a free-text detail field to capture what "other" actually was.

Now your schema stays valid for unforeseen inputs, you don't lose information, and you can mine the detail field to decide if a new enum value is warranted.

"category": {
    "type": "string",
    "enum": ["hardware", "software", "services", "other"]
},
"category_detail": {
    "type": "string",
    "description": "If category is 'other', describe it here. Omit otherwise."
}

Descriptions Do the Teaching

Field descriptions are mini-prompts. Vague keys produce vague output. Spell out the format, give an example, and state edge-case handling right in the schema.

This is the structured-output equivalent of explicit criteria beating vague instructions: "ISO 8601 date, omit if absent" beats a bare due_date: string every time.

"line_items": {
    "type": "array",
    "description": "One object per billed line. Empty array if none.",
    "items": {
        "type": "object",
        "properties": {
            "sku": {"type": "string", "description": "e.g. 'ABC-1024'"},
            "qty": {"type": "integer"},
            "unit_price": {"type": "number"}
        },
        "required": ["qty", "unit_price"]
    }
}

Build in Self-Verification

Great schemas help you catch errors. To verify arithmetic, extract BOTH a calculated and a stated value, then compare them in code.

For example, capture stated_total (printed on the doc) alongside the line items you can sum yourself. A mismatch flags an extraction or document error before it propagates downstream.

"stated_total": {
    "type": "number",
    "description": "The grand total exactly as printed on the invoice."
}
# In code:
# calc = sum(li['qty'] * li['unit_price'] for li in items)
# if abs(calc - data['stated_total']) > 0.01: flag_discrepancy()

Validate, Then Retry with Feedback

The schema guarantees JSON shape, not business correctness. Layer Pydantic-style validation on top. When it fails on a format / structural / arithmetic error, retry — but feed the model what went wrong.

Send the original document, the wrong output, and the exact validation error. That's retry-with-feedback. Note: retrying does NOT help when information is simply absent from the source — no amount of re-asking conjures missing data.

messages = [
    {"role": "user", "content": original_doc},
    {"role": "assistant", "content": wrong_output},
    {"role": "user", "content":
        f"Validation failed: {error}. Re-emit corrected JSON."},
]
# Retry fixes format/arithmetic bugs, not missing facts.

Capture Provenance in the Schema

For extraction you'll defend later, design fields that preserve provenance: where each claim came from. Keep claim-to-source mappings — source name, quote, page or date.

This turns a black-box extraction into an auditable one, and lets you annotate conflicting values (often a date difference) instead of silently picking one.

"items": {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "value": {"type": "string"},
            "source_quote": {"type": "string",
                "description": "Verbatim text supporting this value."},
            "source_page": {"type": "integer"}
        },
        "required": ["value", "source_quote"]
    }
}

Quick Check: Optional Field

You're extracting purchase orders. Some POs list a discount_code, but most do not. How should the schema treat discount_code?

Recap: Shaping the Output

Key takeaways for designing a JSON Schema:

  • tool_use + JSON Schema kills syntax errors and enforces required fields.
  • Force shape with tool_choice: "any" for some tool, {"type":"tool","name":"X"} for a specific one.
  • Mark required ONLY for always-present fields — requiring an absent field causes fabrication.
  • Use enums for fixed vocabularies; add "other" + a detail field for extensibility.
  • Descriptions teach format, examples, and edge cases.
  • Extract calculated AND stated values to self-verify; validate, then retry-with-feedback for format errors (not for absent info).
  • Capture provenance for auditable, defensible extraction.

常见问题解答

「设计 JSON 模式」课时是免费的吗?

是的 — 「设计 JSON 模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Claude Architect 课程的其余内容,请升级到 CoddyKit PRO。 Claude Architect 课程共包含 4 节课。

「设计 JSON 模式」这节课中我会学到什么?

将输出塑造成您确切需要的形式。 你通过在浏览器中直接运行的动手代码来练习 Claude Architect,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Claude Architect 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Claude Architect 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「设计 JSON 模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Claude Architect 课中编写并运行代码吗?

能。每节 Claude Architect 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 tool_use 保证结构
  2. 设计 JSON 模式
  3. 必填字段与可选/可为空字段
  4. 使用带有“other”的枚举实现可扩展性
← 返回 Claude Architect