Skip to content

Comments

fix: normalize structured_output to handle wrapper keys and stringified JSON#532

Open
wingding12 wants to merge 1 commit intoanthropics:mainfrom
wingding12:fix/structured-output-wrapper-502-510
Open

fix: normalize structured_output to handle wrapper keys and stringified JSON#532
wingding12 wants to merge 1 commit intoanthropics:mainfrom
wingding12:fix/structured-output-wrapper-502-510

Conversation

@wingding12
Copy link

Summary

Fix two common issues with model-generated structured output that cause schema validation failures and silent None results:

Issue #502: Wrapper Keys

Model sometimes wraps data in {"output": {...}}, {"response": {...}}, {"json": {...}}, etc. This causes schema validation to fail because the wrapper key is an "additional property".

Before: {"output": {"actions": [...]}} → schema validation fails
After: {"actions": [...]} → works correctly

Issue #510: Stringified JSON Arrays

Model sometimes serializes arrays as JSON strings like "[{\"field\": ...}]" instead of native arrays. This causes repeated validation failures with errors like .items: should be array.

Before: {"items": "[{\"field\": \"value\"}]"} → validation fails
After: {"items": [{"field": "value"}]} → works correctly

Changes

  • src/claude_agent_sdk/_internal/message_parser.py: Added _normalize_structured_output() and _parse_stringified_json() functions that:

    • Unwrap common wrapper keys (output, response, json, data, result)
    • Recursively parse stringified JSON back to native Python types
    • Applied during ResultMessage parsing
  • tests/test_structured_output_normalization.py: Added 25 tests covering:

    • Wrapper key unwrapping
    • Stringified JSON parsing
    • Combined scenarios
    • Edge cases (empty arrays, invalid JSON, etc.)

Test Plan

  • All 25 new tests pass
  • All 22 existing message parser tests pass
  • Ruff linting passes

Fixes #502
Fixes #510

…ed JSON

Fix two common issues with model-generated structured output:

1. Wrapper keys (anthropics#502): Model sometimes wraps data in {"output": {...}},
   {"response": {...}}, {"json": {...}}, etc. This fix unwraps single-key
   dicts with common wrapper keys to return just the inner data.

2. Stringified JSON (anthropics#510): Model sometimes serializes arrays/objects
   as JSON strings instead of native arrays. This fix recursively parses
   such strings back to native Python types.

The normalization is applied when parsing ResultMessage, so users get
clean structured_output without needing to handle these edge cases.

Fixes anthropics#502
Fixes anthropics#510
@wingding12 wingding12 closed this Jan 29, 2026
@jessesanford
Copy link

@wingding12 why so closed?

@abhinav922
Copy link

Why is this closed without being merged? we are still facing this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants