पाठ 17 / 25

JSON APIs and HTTP Clients

Build JSON responses and call external APIs safely.

Speaking JSON in both directions

Most modern PHP applications serve or consume JSON. Encode with json_encode($data, JSON_THROW_ON_ERROR), adding flags such as JSON_UNESCAPED_UNICODE (keep Hindi text readable) and JSON_UNESCAPED_SLASHES where appropriate; decode with json_decode($json, true, 512, JSON_THROW_ON_ERROR) to get associative arrays, or map into typed objects with libraries such as Symfony Serializer or Valinor. PHP 8.3 added json_validate() to check syntax without decoding. Set Content-Type: application/json and correct status codes on responses. Implement JsonSerializable to control how objects are encoded. For outgoing HTTP calls, use a robust client: Guzzle or Symfony HttpClient (both widely used, and PSR-18 compatible clients can be swapped behind Psr\Http\Client\ClientInterface). Always set timeouts (connect and total), handle non-2xx responses explicitly, retry only idempotent requests with backoff, and never log full responses that may contain personal data or secrets.

A JSON endpoint and a Guzzle call with timeouts

Encoding objects, decoding safely and calling an external API.

<?php
declare(strict_types=1);

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

final class OrderView implements JsonSerializable
{
    public function __construct(private string $id, private int $totalPaise, private OrderStatus $status) {}

    public function jsonSerialize(): array
    {
        return ['id' => $this->id, 'total' => number_format($this->totalPaise / 100, 2, '.', ''), 'status' => $this->status->value];
    }
}

header('Content-Type: application/json; charset=utf-8');
echo json_encode(['data' => $orderViews], JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);

$http = new Client(['base_uri' => 'https://rates.example.com', 'connect_timeout' => 2, 'timeout' => 5]);
try {
    $response = $http->get('/v1/rates', ['query' => ['base' => 'USD']]);
    $rates = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);
    $inr = $rates['rates']['INR'] ?? throw new UnexpectedValueException('INR rate missing');
} catch (GuzzleException | JsonException $e) {
    $logger->warning('Rate lookup failed', ['error' => $e->getMessage()]);
    $inr = $cache->get('last_inr_rate');      // fall back to the last known value
}

Translating for a foreign client

json_encode is the translator who turns your notes into a language every system understands; the timeout is your rule that if the other side does not answer within five seconds, you move on with yesterday's figures.

त्वरित जाँच: Which json_decode option makes invalid JSON throw an exception instead of returning null?

  • JSON_PRETTY_PRINT
  • JSON_THROW_ON_ERROR
  • JSON_UNESCAPED_UNICODE
  • JSON_FORCE_OBJECT
Answer

JSON_THROW_ON_ERROR — JSON_THROW_ON_ERROR raises JsonException so failures cannot pass silently.