OpenAI-Compatible JSON Mode: Test response_format and Fix Invalid JSON

JSON Mode asks the endpoint for one valid JSON object. It does not enforce your keys, types, or JSON Schema. Test syntax and shape as separate contracts.

Published
Updated
Reading time
8 minutes
PARAMETEREndpoint accepts response_format
SYNTAXContent parses as JSON
SHAPETop-level value is an object
FIELDSApplication validates required keys

The Short Answer

Send response_format: {"type":"json_object"}. Also tell the model to return JSON. Parse the content and validate the result in your application.

  1. 1

    Confirm that the endpoint accepts the response_format parameter.

  2. 2

    Remove an optional markdown fence before parsing.

  3. 3

    Parse the complete assistant content as JSON.

  4. 4

    Validate the object, required keys, and value types.

Run the JSON Mode probe

Send a Minimal JSON Mode Request

Keep the first request small. Ask for one object with two string fields. This request separates parameter support from complex prompt behavior.

Chat Completions JSON Mode request
curl https://api.example.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-model-id",
    "messages": [{
      "role": "user",
      "content": "Return one JSON object with city and country string fields. Use JSON only."
    }],
    "response_format": {"type": "json_object"}
  }'

OpenAI defines JSON Mode as json_object and states that it does not enforce a schema. Read the official JSON Mode comparison. Source checked 12 Aug 2026.

Do Not Confuse JSON Mode with Structured Outputs

MethodSyntax guaranteeSchema guarantee
Prompt onlyNoNo
json_objectExpected when supportedNo
json_schema with strict modeYes when supportedYes for supported schemas
LLMCompat tests JSON Mode, not strict JSON Schema

The current probe checks valid JSON, the top-level object, and requested keys. It does not claim strict schema compatibility.

Map Each Result to the Failed Contract

SymptomLikely layerAction
400 names response_formatServer capabilityUse prompt constraints and client validation, or change runtime
Plain proseIgnored parameterTreat JSON Mode as unavailable
JSON inside a code fenceModel behaviorStrip the fence before parsing
Valid array or scalarShape mismatchReject values that are not objects
Object has wrong keysInstruction followingValidate keys and retry with clear errors
Truncated JSONGeneration limitCheck token limits and the finish reason
Minimal client-side guard
const raw = response.choices[0].message.content;

const normalized = raw
  .replace(/^\s*```(?:json)?\s*/i, "")
  .replace(/\s*```\s*$/, "");

const value = JSON.parse(normalized);
if (!value || Array.isArray(value) || typeof value !== "object") {
  throw new Error("Expected one JSON object");
}

Verify Support with Raw Evidence

LLMCompat stores the request, response, raw content, parse result, and each failed check. Use that evidence before you change prompts or SDK code.