taptools/blog/Debugging Malformed JSON
JSONMay 16, 2026 · 7 min read

Debugging Malformed JSON API Responses

Getting a JSON parse error from an API response is one of the most frustrating debugging experiences. This guide shows you exactly how to identify and fix malformed JSON from any API.

Why APIs return malformed JSON

APIs return malformed JSON for many reasons — server errors that return HTML instead of JSON, encoding issues, partial responses from network interruptions or bugs in the serialization logic. Understanding the cause helps you fix it faster.

Server error returning HTML

<!DOCTYPE html><html>500 Internal Server Error</html>

Fix: Check response status code before parsing

Encoding mismatch

{"name": "caf\u00e9"}  vs  {"name": "café"}

Fix: Specify UTF-8 encoding in your request headers

Truncated response

{"users": [{"id": 1, "name": "James"

Fix: Check network timeout settings and response size limits

BOM character at start

{"key": "value"}

Fix: Strip the BOM before parsing

Step by step debugging approach

1

Check the HTTP status code first

// Always check status before parsing
const response = await fetch('https://api.example.com/data')

if (!response.ok) {
  const text = await response.text()
  console.error('API error:', response.status, text)
  throw new Error(`HTTP ${response.status}`)
}

const data = await response.json()
2

Log the raw response text

// Get raw text before parsing
const response = await fetch(url)
const text = await response.text()
console.log('Raw response:', text)

// Now try to parse
try {
  const data = JSON.parse(text)
} catch (e) {
  console.error('Parse error at position:', e.message)
  // Paste the text into taptools JSON formatter
  // to see exactly where the error is
}
3

Check Content-Type header

const contentType = response.headers.get('content-type')
console.log('Content-Type:', contentType)

// Should be: application/json
// If it's text/html — server returned an error page
// If it's text/plain — server returned plain text
4

Use JSON formatter to identify the error

Copy the raw response and paste it into ourJSON Formatter— it shows exactly where the syntax error is and attempts to auto-fix it.

Common malformed JSON patterns and fixes

Python APIs returning single quotes

Python's str() and print() use single quotes. If someone accidentally serializes using str() instead of json.dumps() the output is not valid JSON.

# Python bug — using str() instead of json.dumps()
data = {'name': 'James', 'active': True}
return str(data)  # ❌ Returns Python dict string
# {'name': 'James', 'active': True}  ← not valid JSON
import json
return json.dumps(data)  # ✅ Valid JSON
# {"name": "James", "active": true}

Java APIs returning unquoted values

Manual string concatenation in Java controllers often produces invalid JSON with missing quotes or incorrect escaping.

// Java bug — string concatenation
String json = "{name: " + name + ", age: " + age + "}"
// ❌ Produces: {name: James, age: 30}
// Use ObjectMapper (Jackson)
ObjectMapper mapper = new ObjectMapper()
String json = mapper.writeValueAsString(userObject)
// ✅ Produces: {"name":"James","age":30}

APIs returning undefined or NaN values

JavaScript's JSON.stringify handles undefined and NaN poorly. undefined values are omitted entirely and NaN becomes null.

const data = {
  name:  "James",
  score: NaN,       // becomes null in JSON
  extra: undefined  // omitted from JSON
}

JSON.stringify(data)
// {"name":"James","score":null}

Safe JSON parsing wrapper

// Safe JSON parse with detailed error info
function safeJsonParse(text, source = 'API') {
  try {
    return { data: JSON.parse(text), error: null }
  } catch (e) {
    // Extract position from error message
    const posMatch = e.message.match(/position (\d+)/)
    const position = posMatch ? parseInt(posMatch[1]) : null

    if (position !== null) {
      const start   = Math.max(0, position - 20)
      const end     = Math.min(text.length, position + 20)
      const context = text.slice(start, end)
      console.error(`${source} JSON error near: "${context}"`)
    }

    return { 
      data:  null, 
      error: e.message,
      raw:   text.slice(0, 200) // first 200 chars for debugging
    }
  }
}

Fix malformed JSON instantly

Paste your broken JSON and our formatter will identify and auto-fix the most common errors.

Open JSON Formatter →