PHP Fundamentals
Working with JSON
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:
- Create a PHP array representing a blog post and convert it to JSON
- Read a JSON file containing products and display them in an HTML table
- Build a simple API endpoint that returns user data in JSON format
- Write a function that validates JSON against a schema and returns detailed errors
- 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/jsonheader for API responses - Use
JSON_PRETTY_PRINTfor human-readable output - Use
JSON_UNESCAPED_UNICODEfor international characters - Implement
JsonSerializablefor 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!