PHP Fundamentals

Working with JSON

13 min Lesson 15 of 45

Working with JSON in PHP

JSON (JavaScript Object Notation) is a lightweight, text-based data interchange format that's easy for humans to read and write, and easy for machines to parse and generate. It's the de facto standard for web APIs and data exchange.

Note: JSON is language-independent but uses conventions familiar to programmers of the C-family of languages, including PHP. Understanding JSON is essential for modern web development.

JSON Basics

JSON supports these data types:

  • String: "hello"
  • Number: 42, 3.14
  • Boolean: true, false
  • Null: null
  • Array: [1, 2, 3]
  • Object: {"key": "value"}
{ "name": "John Doe", "age": 30, "isActive": true, "email": null, "hobbies": ["reading", "coding", "gaming"], "address": { "city": "New York", "zip": "10001" } }

Encoding PHP to JSON (json_encode)

Convert PHP arrays and objects to JSON strings:

<?php // Simple array to JSON $colors = ["red", "green", "blue"]; $json = json_encode($colors); echo $json; // ["red","green","blue"] // Associative array to JSON object $person = [ "name" => "John Doe", "age" => 30, "email" => "john@example.com" ]; $json = json_encode($person); echo $json; // {"name":"John Doe","age":30,"email":"john@example.com"} // Nested arrays $data = [ "users" => [ ["id" => 1, "name" => "Alice"], ["id" => 2, "name" => "Bob"] ], "total" => 2 ]; $json = json_encode($data); echo $json; ?>

json_encode() Options

<?php $data = [ "name" => "John", "city" => "New York", "hobbies" => ["reading", "coding"] ]; // Pretty print (readable format) echo json_encode($data, JSON_PRETTY_PRINT); /* { "name": "John", "city": "New York", "hobbies": [ "reading", "coding" ] } */ // Preserve Unicode characters $arabic = ["greeting" => "مرحبا"]; echo json_encode($arabic); // {"greeting":"\u0645\u0631\u062d\u0628\u0627"} echo json_encode($arabic, JSON_UNESCAPED_UNICODE); // {"greeting":"مرحبا"} // Don't escape slashes $url = ["website" => "https://example.com"]; echo json_encode($url, JSON_UNESCAPED_SLASHES); // {"website":"https://example.com"} // Force object notation for empty arrays $empty = []; echo json_encode($empty); // [] echo json_encode($empty, JSON_FORCE_OBJECT); // {} // Combine multiple options echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); ?>
Tip: Use JSON_PRETTY_PRINT for debugging and JSON_UNESCAPED_UNICODE when working with international characters.

Decoding JSON to PHP (json_decode)

Convert JSON strings to PHP arrays or objects:

<?php $json = '{"name":"John","age":30,"city":"NYC"}'; // Decode to associative array (default: object) $data = json_decode($json, true); print_r($data); // Array ( [name] => John [age] => 30 [city] => NYC ) echo $data["name"]; // John // Decode to object $obj = json_decode($json); print_r($obj); // stdClass Object ( [name] => John [age] => 30 [city] => NYC ) echo $obj->name; // John // Nested JSON $json = '{"user":{"name":"Alice","email":"alice@example.com"},"posts":3}'; $data = json_decode($json, true); echo $data["user"]["name"]; // Alice ?>

json_decode() Options

<?php $json = '{"name":"John","age":30}'; // Specify depth (max nesting level) $data = json_decode($json, true, 512); // Decode with flags $data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING); // Handle large integers as strings (prevent precision loss) $json = '{"id":9223372036854775807}'; // Large number $data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING); echo $data["id"]; // "9223372036854775807" (string) ?>

Error Handling

Always check for errors when working with JSON:

<?php // Encoding errors $data = ["text" => "\xB1\x31"]; // Invalid UTF-8 $json = json_encode($data); if ($json === false) { echo "JSON encoding error: " . json_last_error_msg(); // Output: JSON encoding error: Malformed UTF-8 characters } // Decoding errors $json = '{"name":"John",}'; // Invalid JSON (trailing comma) $data = json_decode($json, true); if ($data === null && json_last_error() !== JSON_ERROR_NONE) { echo "JSON decoding error: " . json_last_error_msg(); // Output: JSON decoding error: Syntax error } // Using json_last_error() switch (json_last_error()) { case JSON_ERROR_NONE: echo "No error"; break; case JSON_ERROR_DEPTH: echo "Maximum stack depth exceeded"; break; case JSON_ERROR_SYNTAX: echo "Syntax error, malformed JSON"; break; case JSON_ERROR_UTF8: echo "Malformed UTF-8 characters"; break; default: echo "Unknown error"; } ?>
Warning: Always validate JSON data before decoding. json_decode() returns null for both empty input and invalid JSON, so always check json_last_error().

Practical Examples

Working with API Responses

<?php // Simulate API response $apiResponse = ' { "status": "success", "data": { "users": [ {"id": 1, "name": "Alice", "email": "alice@example.com"}, {"id": 2, "name": "Bob", "email": "bob@example.com"} ] }, "meta": { "total": 2, "page": 1 } } '; // Parse response $response = json_decode($apiResponse, true); if ($response === null) { die("Invalid JSON response"); } // Access data if ($response["status"] === "success") { $users = $response["data"]["users"]; foreach ($users as $user) { echo "{$user['name']} ({$user['email']})<br>"; } echo "Total: {$response['meta']['total']}<br>"; } ?>

Creating API Responses

<?php // Set proper content type header("Content-Type: application/json"); // Success response function jsonResponse($data, $status = 200) { http_response_code($status); echo json_encode([ "success" => true, "data" => $data ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } // Error response function jsonError($message, $status = 400) { http_response_code($status); echo json_encode([ "success" => false, "error" => $message ], JSON_PRETTY_PRINT); } // Usage $users = [ ["id" => 1, "name" => "Alice"], ["id" => 2, "name" => "Bob"] ]; jsonResponse($users, 200); // Or for errors // jsonError("User not found", 404); ?>

Reading and Writing JSON Files

<?php // Write JSON to file $data = [ "users" => [ ["name" => "Alice", "age" => 25], ["name" => "Bob", "age" => 30] ], "updated" => date("Y-m-d H:i:s") ]; $json = json_encode($data, JSON_PRETTY_PRINT); file_put_contents("data.json", $json); // Read JSON from file $json = file_get_contents("data.json"); $data = json_decode($json, true); if ($data === null) { die("Error reading JSON file"); } print_r($data); // Update and save $data["users"][] = ["name" => "Charlie", "age" => 28]; $data["updated"] = date("Y-m-d H:i:s"); file_put_contents("data.json", json_encode($data, JSON_PRETTY_PRINT)); ?>

JSON and PHP Objects

<?php class User { public $name; public $email; private $password; // Won't be included in JSON public function __construct($name, $email, $password) { $this->name = $name; $this->email = $email; $this->password = $password; } } // Encode object to JSON $user = new User("John", "john@example.com", "secret123"); $json = json_encode($user); echo $json; // {"name":"John","email":"john@example.com"} // Decode JSON to specific class (PHP 7.0+) $json = '{"name":"Alice","email":"alice@example.com"}'; $user = json_decode($json); // stdClass // Custom JSON representation class Product implements JsonSerializable { private $id; private $name; private $price; public function __construct($id, $name, $price) { $this->id = $id; $this->name = $name; $this->price = $price; } public function jsonSerialize(): mixed { return [ "id" => $this->id, "name" => $this->name, "price" => number_format($this->price, 2), "currency" => "USD" ]; } } $product = new Product(1, "Laptop", 999.99); echo json_encode($product); // {"id":1,"name":"Laptop","price":"999.99","currency":"USD"} ?>
Tip: Implement JsonSerializable interface to control exactly how your objects are converted to JSON.

JSON Validation

<?php function isValidJson($string) { json_decode($string); return json_last_error() === JSON_ERROR_NONE; } // Validate JSON $json = '{"name":"John","age":30}'; if (isValidJson($json)) { echo "Valid JSON"; } else { echo "Invalid JSON"; } // Validate structure function validateJsonStructure($json, $requiredKeys) { $data = json_decode($json, true); if ($data === null) { return ["error" => "Invalid JSON"]; } $errors = []; foreach ($requiredKeys as $key) { if (!isset($data[$key])) { $errors[] = "Missing required key: $key"; } } return empty($errors) ? true : $errors; } // Usage $json = '{"name":"John","email":"john@example.com"}'; $result = validateJsonStructure($json, ["name", "email", "age"]); if ($result === true) { echo "Valid structure"; } else { print_r($result); // ["Missing required key: age"] } ?>

Advanced JSON Techniques

Streaming Large JSON Files

<?php // For large JSON files, use streaming to avoid memory issues function streamJsonArray($filename, $callback) { $handle = fopen($filename, "r"); if (!$handle) return false; $buffer = ""; $inArray = false; $bracketCount = 0; while (($char = fgetc($handle)) !== false) { if ($char === "[") { $inArray = true; continue; } if ($inArray) { if ($char === "{") $bracketCount++; if ($char === "}") $bracketCount--; $buffer .= $char; if ($bracketCount === 0 && trim($buffer)) { $item = json_decode(trim($buffer, ","), true); if ($item) $callback($item); $buffer = ""; } } } fclose($handle); } // Usage: Process items one at a time streamJsonArray("large-data.json", function($item) { echo $item["name"] . "<br>"; }); ?>

JSON Schema Validation

<?php // Simple JSON schema validator function validateJsonSchema($data, $schema) { $errors = []; foreach ($schema as $field => $rules) { if ($rules["required"] && !isset($data[$field])) { $errors[] = "$field is required"; continue; } if (!isset($data[$field])) continue; $value = $data[$field]; // Type validation if (isset($rules["type"])) { $actualType = gettype($value); if ($actualType !== $rules["type"]) { $errors[] = "$field must be {$rules['type']}"; } } // Format validation if (isset($rules["format"])) { switch ($rules["format"]) { case "email": if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { $errors[] = "$field must be valid email"; } break; case "url": if (!filter_var($value, FILTER_VALIDATE_URL)) { $errors[] = "$field must be valid URL"; } break; } } } return empty($errors) ? true : $errors; } // Usage $data = [ "name" => "John", "email" => "invalid-email", "age" => "30" ]; $schema = [ "name" => ["required" => true, "type" => "string"], "email" => ["required" => true, "type" => "string", "format" => "email"], "age" => ["required" => true, "type" => "integer"] ]; $result = validateJsonSchema($data, $schema); print_r($result); ?>
Exercise:
  1. Create a PHP array representing a blog post and convert it to JSON
  2. Read a JSON file containing products and display them in an HTML table
  3. Build a simple API endpoint that returns user data in JSON format
  4. Write a function that validates JSON against a schema and returns detailed errors
  5. Create a function that transforms nested PHP arrays to dot-notation JSON and back

Common Use Cases

  • API Communication: Send and receive data from REST APIs
  • Configuration Files: Store application settings in JSON format
  • Data Storage: Use JSON files as lightweight databases
  • AJAX Responses: Return structured data to JavaScript
  • Logging: Store structured log entries
  • Caching: Serialize complex data structures for caching

Best Practices

  • Always validate JSON before decoding
  • Use json_last_error() to check for encoding/decoding errors
  • Set proper Content-Type: application/json header for API responses
  • Use JSON_PRETTY_PRINT for human-readable output
  • Use JSON_UNESCAPED_UNICODE for international characters
  • Implement JsonSerializable for custom object serialization
  • Be cautious with large JSON files - consider streaming
  • Always escape user input before encoding to prevent XSS
Warning:
  • JSON keys must be strings (not integers) for objects
  • Floating-point precision can be lost in JSON encoding
  • PHP's null, false, and empty string "" are different in JSON
  • Large integers may lose precision - use JSON_BIGINT_AS_STRING
  • JSON doesn't support comments - remove them before parsing

Summary

In this lesson, you learned:

  • What JSON is and its data types
  • How to encode PHP arrays/objects to JSON with json_encode()
  • How to decode JSON to PHP with json_decode()
  • JSON encoding/decoding options and error handling
  • Working with API responses and creating API endpoints
  • Reading and writing JSON files
  • Converting PHP objects to JSON and vice versa
  • Validating JSON structure and schemas
  • Advanced techniques like streaming and custom serialization

JSON is fundamental to modern web development. Master it well - you'll use it constantly when building APIs, working with JavaScript, and integrating with third-party services!