Blog
Wild & Free Tools

Escape JSON in PHP — json_encode Options Explained

Last updated: March 2026 6 min read
Quick Answer

Table of Contents

  1. The Default Surprises
  2. Fixing the Defaults
  3. Why the Forward Slash Default?
  4. json_decode and Escaping Back
  5. Escaping Strings for Inclusion
  6. Frequently Asked Questions

PHP's json_encode has the most surprising default behavior of any major JSON library. It escapes forward slashes (which JSON doesn't require) and non-ASCII characters (which JSON allows raw). The output is still valid JSON, but it's noisier than what JavaScript, Python, or Java produce for the same input. A one-flag fix makes PHP's output match everything else.

What PHP Does By Default

Compare the same data serialized by PHP vs Node:

// PHP
echo json_encode(["url" => "https://example.com/path", "name" => "café"]);
// {"url":"https:\/\/example.com\/path","name":"caf\u00e9"}

// Node
JSON.stringify({url: "https://example.com/path", name: "café"})
// {"url":"https://example.com/path","name":"café"}

Two differences: PHP escapes forward slashes as \/, and escapes non-ASCII as \u sequences. Both are valid JSON. Both parse back to the same data. But for log readability, byte-for-byte cross-language comparison, or just not confusing your future self — you usually want the unescaped form.

Fixing the Defaults With Flags

The two flags you almost always want:

json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

Now PHP produces the same output as Node:

{"url":"https://example.com/path","name":"café"}

Other useful flags:

A sensible default encode call for most modern PHP:

json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
Sell Custom Apparel — We Handle Printing & Free Shipping

Why Does PHP Escape Forward Slashes By Default?

The historical reason: HTML embedding safety. If JSON containing </script> is embedded inside an HTML script tag without slash escaping, the browser sees the literal </script> and closes the script tag, breaking the page.

Escaping the slash as \/ prevents this — the browser sees a regular text character, and your JSON stays intact inside the script tag.

In modern web apps this is handled at the rendering layer (Blade, Twig, React, Vue all escape output automatically). You no longer need PHP's slash escaping for safety, which is why the flag to turn it off is the norm.

For APIs where PHP serializes JSON to a Content-Type: application/json response, there's no HTML context and no safety benefit. Turn it off.

json_decode Handles Unescaping Correctly

The reverse direction is json_decode:

$json = '{"url":"https:\/\/example.com"}';
$data = json_decode($json, true);
echo $data['url'];
// https://example.com

The true second argument returns associative arrays instead of objects — usually what you want in modern PHP. Without it, you get stdClass objects.

Error handling: json_decode returns null on failure. Check with json_last_error(), or better, use JSON_THROW_ON_ERROR on PHP 7.3+:

try {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    // Handle parse error
}

Escaping a Single String For Inclusion in JSON

For cases where you're building JSON by hand (usually a bad idea — let json_encode do the work) and need to escape a single string value:

$escaped = json_encode($inputString);
// Returns: "value with \"quotes\" escaped"

This returns the quoted, escaped string literal. Use it directly inside a larger JSON string if you're building one:

$json = '{"msg":' . json_encode($userMessage) . '}';

Better: build the structure as an array and json_encode the whole thing:

$json = json_encode(['msg' => $userMessage]);

The second approach is safer, shorter, and correct by construction. String concatenation of JSON is a category of bugs; let the library handle the boundaries.

Escape JSON Outside PHP

For log debugging and cross-language JSON. Browser-based, no PHP runtime.

Open Free JSON Escape / Unescape Tool

Frequently Asked Questions

Why does PHP escape my URLs as https:\/\/?

Historical HTML-embedding safety default. Pass JSON_UNESCAPED_SLASHES to json_encode to stop it.

How do I keep UTF-8 characters raw in PHP JSON output?

Pass JSON_UNESCAPED_UNICODE. Combine with JSON_UNESCAPED_SLASHES for Node-compatible output.

Should I use json_encode or manual string building?

Always json_encode. Manual building is a source of bugs and security issues. Build an array; serialize the array.

Why does json_decode return null sometimes?

Invalid JSON. Check json_last_error() for the specific reason, or use JSON_THROW_ON_ERROR for exceptions.

David Rosenberg
David Rosenberg Technical Writer

David spent ten years as a software developer before shifting to technical writing covering developer productivity tools.

More articles by David →
Launch Your Own Clothing Brand — No Inventory, No Risk