JSON Schema for Contact Info Extraction: A Technical Guide
How to design a JSON Schema for reliable contact info extraction with LLMs — structured outputs, function calling, and common pitfalls.

Ask an LLM for structured contact data, and you'll get inconsistent formats, occasionally malformed JSON, and field names that drift between calls — "phone" one response, "phone_number" the next. The fix isn't better prompting; it's treating the output shape as an explicit contract rather than a hope. This is a guide to designing a JSON Schema for contact info extraction (name, email, phone, address) specifically, and more importantly, understanding the different mechanisms that actually enforce that schema, since they don't all guarantee the same thing.
One scope note upfront: "JSON Schema for contact info" also gets used for Schema.org/JSON-LD website markup (ContactPoint, ContactPage) — an unrelated SEO concept for helping search engines find a business's published contact info on a webpage. This guide is about extraction, not website markup.
JSON Schema itself is a specification for describing what a piece of JSON data should look like, which fields exist, what type each one is, and what rules they need to satisfy — so that whatever generates the data and whatever reads it are working from the same agreed-upon shape, rather than one side guessing at what the other expects.
Who This Is For
- Developers building extraction pipelines — LLM-based, document-AI-based, or both, that need contact information pulled into a consistent, predictable structure.
- Anyone integrating structured outputs or function calling with OpenAI, Anthropic, Gemini, or an open-weight model, using contact extraction as a concrete example.
- Teams designing schemas for CRM enrichment, lead capture, or contact deduplication pipelines ingesting unstructured text or documents.
Three Ways to Get JSON Out of an LLM (and They're Not Equally Reliable)
This is the part most guides skip, and it matters more than the schema itself:
- Native structured outputs. You define the exact JSON shape and the API enforces it at generation time — the model literally cannot produce output that violates the schema. This is the strongest guarantee available.
- Function/tool calling. The model calls a predefined function with structured parameters matching your schema, originally designed for triggering external actions, but commonly repurposed purely for structured extraction, since it produces the same schema-conformant output as a side effect.
- Non-native, prompt-based approaches. You describe the desired JSON shape in the prompt and parse the response yourself, often with a validate-and-retry loop. Works with any model, no vendor lock-in, but nothing guarantees the model actually complies, and it will occasionally add commentary, use trailing commas, or invent field names.
The mechanism underneath native structured outputs, when it's genuinely enforced, is constrained (guided) decoding — the schema is compiled into a constraint on the model's next-token generation, so it's literally incapable of generating a token that would violate the schema. This is different from a provider that shows the model the schema as an instruction and trusts it to comply, some providers do the former, some effectively do the latter, and the difference matters: even with a schema, 100% reliability is never fully guaranteed across every provider and method, so validation on your side remains necessary regardless of which approach you use.
Methods and Tools for Extracting JSON Schemas
Pydantic
The standard way to define a schema in Python — you write a typed class, and the library generates a JSON Schema from it automatically rather than requiring you to hand-write raw JSON Schema syntax. It's the foundation most other Python tools in this space (Instructor, PydanticAI) are built directly on top of.
- Type: Data validation and schema-definition library
- Language/Platform: Python
- Best For: Defining schemas in code for Python-based extraction pipelines
- Schema Standard Supported: Generates standard JSON Schema from Python type definitions
- Key Limitation: Python-only, and it's a schema/validation layer; it doesn't itself call an LLM or enforce output at generation time.
Zod
The TypeScript equivalent of Pydantic — define your shape as a Zod schema, and libraries like the OpenAI SDK's zodResponseFormat helper convert it into the JSON Schema the API expects.
- Type: Schema declaration and validation library
- Language/Platform: TypeScript / JavaScript
- Best For: Defining schemas in code for TypeScript-based extraction pipelines
- Schema Standard Supported: Convertible to standard JSON Schema via provider-specific helpers
- Key Limitation: TypeScript/JavaScript-only; like Pydantic, a schema/validation layer rather than an extraction mechanism itself
Instructor
An open-source library, available in Python, TypeScript, Go, Ruby, and more, that wraps LLM calls with Pydantic-based (or equivalent) schema definitions and handles validation and automatic retries for you. If a response fails validation, Instructor can re-prompt the model rather than requiring you to write that retry logic yourself.
- Type: Structured-extraction wrapper library
- Language/Platform: Python, TypeScript, Go, Ruby, Elixir, Rust
- Best For: Fast, provider-agnostic structured extraction with automatic validation and retries, across 15+ supported providers
- Schema Standard Supported: JSON Schema, via Pydantic (or the equivalent typing system per language)
- Key Limitation: Relies on post-generation validation and retry by default — doesn't itself guarantee compliance at generation time the way constrained decoding does
Outlines
A library implementing constrained decoding directly — rather than validating output after generation and retrying on failure, Outlines constrains what the model can generate at the token level, so invalid output is prevented rather than caught afterward.
- Type: Constrained (guided) decoding library
- Language/Platform: Python; works with locally-hosted or compatible model backends
- Best For: High-throughput pipelines where guaranteed schema compliance and avoiding failed-retry costs matter
- Schema Standard Supported: JSON Schema (compiled into token-level generation constraints)
- Key Limitation: More setup complexity than a validation-only tool; best suited to self-hosted or open-weight models where you control the inference stack directly
Guidance
Another constrained-decoding library, capable of enforcing an arbitrary context-free grammar on model output, not just JSON Schema, useful when your extraction needs go beyond what a schema alone can express, such as conditional structure that depends on earlier extracted values.
- Type: Constrained decoding / grammar-enforcement library
- Language/Platform: Python, with C/Rust bindings; integrates with inference engines like llama.cpp
- Best For: Enforcing complex or conditional output structure beyond what plain JSON Schema can express
- Schema Standard Supported: JSON Schema, plus arbitrary context-free grammars
- Key Limitation: More powerful but more complex to configure than schema-only tools; primarily suited to self-hosted inference setups
OpenAI structured outputs
OpenAI's native mechanism for schema-enforced generation, alongside function calling as a related but separate feature.
- Type: Native provider API feature
- Language/Platform: Any language, via OpenAI's API/SDKs
- Best For: Teams already using OpenAI wanting the strongest first-party enforcement guarantee available on that platform
- Schema Standard Supported: A constrained subset of JSON Schema — check current documentation for exactly which keywords are supported
- Key Limitation: OpenAI-specific and not portable to other providers without reimplementation; coverage varies by model and endpoint
LLM (Simon Willison's CLI tool)
A command-line tool and Python library supporting a --schema option that passes a JSON Schema to any of several supported model backends, plus a concise shorthand syntax (comma-separated field names with optional types) for cases where hand-writing full JSON Schema is more overhead than the extraction task warrants.
- Type: Command-line tool and Python library
- Language/Platform: Python (CLI and library); model-agnostic across its supported backends
- Best For: Quick, scriptable extraction tasks without building a full application around them
- Schema Standard Supported: JSON Schema, plus a concise custom shorthand syntax
- Key Limitation: Best suited to scripting and CLI workflows rather than production application integration; reliability depends on which underlying model backend is used
A practical rule of thumb across these: start with post-generation validation (Instructor, or Zod/Pydantic plus manual retry logic) — it works with any cloud API, needs no extra infrastructure, and covers the large majority of use cases. Reach for pre-generation constraints (Outlines, Guidance) specifically when retry cost or compliance requirements justify the added setup, typically alongside a self-hosted or open-weight model where you control the inference stack directly.
The Practical Workflow
The pattern that shows up consistently across production implementations: define → generate → validate → repair → parse.
- Define the shape once, typically in code (Pydantic or Zod) rather than hand-writing raw JSON Schema.
- Generate by sending that schema to the model via whichever mechanism your provider or tool supports.
- Validate the response against your original schema/type definition in code — a cheap, necessary backstop even when the provider claims to enforce the schema.
- Repair, if validation fails — some implementations use the model itself as a fixer, with a narrow, small-context follow-up request that returns only the corrected JSON.
- Parse last, only after the structure is confirmed clean, into whatever typed object your application actually uses.
Use Case: JSON Schema Extraction
A concrete walk-through: a sales team receives inbound leads as unstructured text — forwarded emails, pasted signature blocks, scanned business cards run through OCR — and needs each one turned into a clean contact record before it lands in the CRM.
Without a schema, the extraction step (whether it's an LLM prompt or a document extraction API) returns whatever shape it feels like — sometimes "phone", sometimes "contact_number", sometimes a single string for two phone numbers separated by a slash. Every inconsistency becomes a bug in the code that maps the output into CRM fields, and that mapping code breaks silently whenever the model or document changes its mind about formatting.
With the contact extraction schema defined below, the same input — regardless of whether it's a forwarded email, a signature block, or a scanned card — comes back in one consistent shape: full_name as a required field, emails and phone_numbers as arrays that handle the zero-or-many case naturally, address as a single nested object. The CRM integration code writes to that one contract exactly once, rather than defensively handling every format variation the extraction step might produce.
The broader pattern this illustrates: JSON Schema extraction earns its value specifically at the boundary between an unreliable input source (unstructured text, a document, a model's raw output) and a system that needs a stable contract (a CRM, a database, a downstream pipeline step). The schema is what makes that boundary predictable.
Provider Differences Worth Knowing
- OpenAI supports native structured outputs with schema enforcement, plus function calling as a separate mechanism.
- Anthropic (Claude) supports structured extraction primarily through tool use, covered above.
- Gemini and other providers offer comparable structured output or function-calling features, with varying levels of schema strictness — confirm current behavior directly rather than assuming parity across providers, since this space changes quickly.
- Self-hosted/open-weight models often rely on inference-server-level constrained decoding (an OpenAI-compatible guided_json or equivalent parameter) rather than a provider-hosted structured-output feature.
Basic Structure of a Contact Extraction Schema

Design decisions worth calling out specifically:
- Emails and phone numbers are arrays, since a document or contact block legitimately can contain more than one — a single-value field either loses data or forces an arbitrary choice about which to keep.
- Address is a nested object, not five flat top-level fields — related data stays together and maps cleanly to how most downstream systems (CRMs, databases) model an address.
- additionalProperties: false is a genuinely useful constraint for LLM-targeted schemas specifically — it stops the model from inventing extra fields you didn't ask for, keeping the output contract tight.
- Keep it as flat as the use case allows. Deep, ambiguous nesting is harder for a model to reliably populate correctly than it is for a human to read — schema complexity should match actual data complexity, not be maximized just because JSON Schema supports it.
Schema Design Principles Specific to LLM Consumption
- Field descriptions matter more than they do for human-facing validation. A vague field name with no description invites inconsistent interpretation across calls; a clear description reduces ambiguity the same way clear documentation reduces bugs.
- Align field values with conventions the model has actually seen in training, where possible. Checking what a model returns without a schema first, then designing the schema to match that natural output rather than fighting it, is a genuinely useful technique.
- Ambiguous or incomplete schemas cause hallucination, not just formatting errors. A JSON Schema is effectively a contract the model has to interpret, not a purely mechanical validation spec.
- Get required, additionalProperties, and nullability right deliberately, not by default. These three settings determine what "success" even means for a given extraction call.
Where Document Extraction APIs Fit
Everything above applies to prompting an LLM directly. A related but distinct category — document/OCR extraction APIs — uses JSON Schema the same way, but to configure extraction from documents (PDFs, scans, images) rather than from arbitrary text passed to a general-purpose LLM. These APIs vary in which JSON Schema keywords they actually support: Landing AI's Extract API, for example, documents a specific supported/ignored/unsupported keyword list, with a strict parameter controlling whether an unsupported keyword causes a partial response (HTTP 206) or a hard error (HTTP 422), and treats fields as effectively nullable regardless of required, returning null rather than erroring when a field isn't found in the document.
Schema-driven document extraction APIs, including DeepRead, per its own product description, follow the same general pattern: define custom fields (a contact-extraction schema like the one above works the same way here) rather than needing per-document-type retraining for each new schema. The same caution applies as with any provider: confirm which JSON Schema keywords a specific API supports and how it handles required/nullable fields in its own documentation, rather than assuming behavior based on the general spec or another vendor's documented behavior.
Common Pitfalls
- Assuming a schema guarantees 100% reliable output. Even with native structured outputs and constrained decoding, validation on your side remains necessary — this is a meaningfully reduced failure rate, not a guarantee.
- Treating required as guaranteeing presence. Behavior varies by provider and API — some return null for missing fields rather than erroring, even when marked required.
- Over-nesting for a simple use case, or under-nesting a genuinely hierarchical one like address data.
- Hand-writing raw JSON Schema instead of generating it from Pydantic/Zod, which is more error-prone to maintain as the schema grows.
- Not testing what the model returns without a schema first, missing the chance to align your schema's conventions with what the model naturally produces.
- Ignoring which keywords a specific extraction API actually supports before designing an elaborate schema.
Conclusion
Reliable contact info extraction from an LLM or document extraction API comes down to two separate things: choosing a mechanism that actually enforces the schema (native structured outputs or constrained decoding via tools like Outlines or Guidance, not just a prompt-embedded description) and designing the schema itself with the model's consumption in mind, arrays for multi-valued fields, nested structure for related data, tight constraints like additionalProperties: false, and descriptions clear enough to reduce ambiguity. Validate on your side regardless of which method or tool you use, since even the strongest schema-enforcement mechanisms available today don't eliminate the need for it.
FAQ
What's the difference between structured outputs and function calling for extraction?
Structured outputs directly enforce the JSON shape you define, with guarantees at generation time in the strongest implementations. Function/tool calling has the model call a predefined function with structured parameters, originally built for triggering actions, but commonly used purely for extraction since it produces equivalent structured output as a side effect.
Does a JSON Schema guarantee an LLM will produce valid output?
Not universally; it depends on the mechanism. Native structured outputs backed by constrained/guided decoding offer the strongest guarantee. Prompt-based, non-native approaches offer no guarantee at all and require validation and retry logic.
Should I use Instructor, Outlines, or hand-roll validation myself?
Instructor is the common default for most projects; it works across many providers with minimal setup and handles the majority of use cases through post-generation validation and retries. Outlines or Guidance are worth the added setup, specifically when retry cost or strict compliance requirements justify pre-generation constrained decoding, typically alongside a self-hosted model.
Is JSON Schema for LLM extraction the same as JSON Schema for document extraction APIs?
The underlying concept is the same, but document extraction APIs (like Landing AI's Extract API or DeepRead) apply it to structuring document output specifically and often support only a subset of JSON Schema keywords, with vendor-specific behavior around required and nullable fields. Confirm a specific API's supported keywords directly rather than assuming full spec support.
Why does field ordering or nesting affect extraction reliability?
Because the schema is a contract the model has to interpret, not just a mechanical validation spec, ambiguous or unconventionally structured schemas are more prone to inconsistent or hallucinated output than schemas using clear descriptions and structure aligned with how the model was trained to produce similar data.
More articles

AI Document Processing for Real Estate: A 2026 Guide
How AI document processing works for commercial real estate - lease abstraction, tenant/vendor management, named tools, and what to evaluate.

Top Healthcare Document Processing Systems for Research Data (2026)
Healthcare document processing tools ranked for research data, clinical extraction, abstraction, and compliance, with a decision framework.