Force an LLM to return JSON in JavaScript

Authors
  • avatar
    Name
    Hamza Rahman
Published on
-
3 mins read

The safest way to get JSON from an LLM is to use a schema-based response format.

This example asks the model to classify a support message and return only the fields your app needs.

Install

npm install openai zod

Set your API key:

export OPENAI_API_KEY="your_api_key_here"

Code

import OpenAI from 'openai'
import { zodTextFormat } from 'openai/helpers/zod'
import { z } from 'zod'
const openai = new OpenAI()
const TicketLabel = z.object({
category: z.enum(['billing', 'bug', 'feature_request', 'other']),
priority: z.enum(['low', 'medium', 'high']),
summary: z.string(),
})
const response = await openai.responses.parse({
model: 'gpt-5.5',
input: [
{
role: 'system',
content: 'Classify the support ticket. Keep the summary under 20 words.',
},
{
role: 'user',
content: 'My invoice was charged twice this month. Please fix it quickly.',
},
],
text: {
format: zodTextFormat(TicketLabel, 'ticket_label'),
},
})
const ticket = response.output_parsed
console.log(ticket.category)
console.log(ticket.priority)
console.log(ticket.summary)

Example output:

{
category: 'billing',
priority: 'high',
summary: 'Customer was charged twice and needs billing correction.'
}

Why not just JSON.parse?

You can ask a model to "return JSON", but plain prompting can still produce invalid JSON, extra text, or missing fields.

Schema-based output is better when the result goes into real application code.

Use it for:

  • Ticket classification
  • Lead enrichment
  • Entity extraction
  • Moderation labels
  • App-ready LLM responses

Common mistakes

  • Prompting "respond in JSON" and then calling JSON.parse on the raw text. It works in a demo, then breaks the first time the model wraps the JSON in prose or a code fence. The schema format above removes that whole class of bug.
  • Forgetting the model can still refuse. A structured response can come back empty if the request is rejected, so check for that before you read fields.
  • Making every field optional. If a field is required for your code to work, mark it required in the schema so a missing value fails loudly instead of silently becoming undefined.

References