قالب وردپرس درنا توس
Home / Tips and Tricks / Working with JSON in PHP – CloudSavvy IT

Working with JSON in PHP – CloudSavvy IT



PHP logo

JSON is one of the most commonly used data serialization formats. It grew from its origins in JavaScript (JSON means JavaScript Object Notation) and has become the format of choice for many web APIs and configuration systems.

PHP comes with built-in JSON support. Historically, the functions were provided as a separate extension. The launch of PHP 8.0 in 2020 turned JSON into a permanently active extension that cannot be removed.

Read JSON data

To parse JSON data, use the json_decode() function. The full signature is as follows:

json_decode(string $json, bool|null $associative=null, int $depth=512, int $flags=0) : mixed;

The simplest call is to pass a JSON string with no other arguments. We will work with it {"foo": "bar"} which decodes to an instance of PHP’s generic stdClass. Our new object is given ownership foo with the value of bar.

If you prefer to receive an associative array, you must pass true to the $associative parameter of json_decode(). The above example would then decode to ["foo" => "bar"].

The $depth parameter you can determine the maximum nest level to parsed to. You get null if the JSON nests deeper than the set level, no attempt will be made to parse the data.

The $flags parameter accepts a bit mask of optional flags that change the parsing behavior. These are detailed in the PHP manual and allow you to define how to handle specific data types.

Dealing with parsing errors

Standard, json_decode() will be back null when it passed an invalid JSON string. This poses a problem because one is isolated null is a valid JSON string. You cannot know if it null return value is due to the JSON with null, or because the JSON was in the wrong format and could not be parsed.

PHP 7.3 finally solved this long-standing problem through the extension JSON_THROW_ON_ERROR flag. Pass this constant to the $flags parameter of json_decode() to have PHP throw an exception when invalid JSON is encountered:

json_decode("['malformed json", true, 512, JSON_THROW_ON_ERROR);

Enabling this behavior is generally desirable, but it makes for a rather unwieldy invocation. You can use PHP 8’s mentioned arguments to simplify things a bit, as you don’t need to pass explicit values ​​for the optional parameters:

json_decode(json: "['malformed json", flags: JSON_THROW_ON_ERROR);

The two examples shown above are equivalent to each other. The only difference is that the last syntax requires PHP 8.

Serialize data to JSON

You can serialize PHP values ​​to JSON strings using the json_encode() function. The signature is as follows:

json_encode(mixed $value, int $flags=0, int $depth=512) : string|false;

PHP accepts any value as $value, except sources. Data types are automatically processed to ensure they have an appropriate mapping in the generated JSON. PHP objects and associative arrays become JSON objects containing all enumerable properties / key value pairs of the input value. PHP scalar types are mapped directly in JSON without transformation.

Like its decoding counterpart, json_encode() accepts $flags and $depth parameters. Be careful with the order though – in a quirk of the PHP standard library the position of these two optional parameters is changed compared to json_decode().

Many more flags are supported when encoding data. Here are some to watch out for:

  • JSON_FORCE_OBJECT Convert PHP numeric arrays to JSON objects instead of arrays. This covers the case where a variable contains an associative array that may be empty. When the array is empty ([]), a JSON array would be created; if it is not empty (["foo" => "bar"]), an object would be emitted instead. Enabling this flag ensures that an object is always used in the encoded JSON.
  • JSON_PRETTY_PRINT – PHP’s JSON output is normally miniaturized, which is ideal when sent over the network as part of an HTTP request. Setting this flag adds new line characters and auto indentation to the JSON string, making it more suitable for configuration files and other scenarios where people will read the output.
  • JSON_PRESERVE_ZERO_FRACTION – Forces PHP to use floats like 0.0 exactly, instead of shaving off the fraction to write 0 in the JSON (which can be incorrectly parsed as an integer).
  • JSON_NUMERIC_CHECK – Automatically converts numeric strings to numbers in the JSON output, instead of keeping them as strings. With this enabled, a PHP value "234.5" is broadcast as 234.5 in the JSON.
  • JSON_PARTIAL_OUTPUT_ON_ERROR – Try to continue writing even after an encoding error has occurred. PHP will try to replace invalid values ​​to produce some output, even if it is incomplete.

You can find the full list of flags in the PHP documentation. The rest are usually specific options to customize the encoding used in certain scenarios.

Bring JSON to the domain layer of your application

Complex web backends most likely use PHP’s JSON functions in the context of sending HTTP responses. That probably means that you will be encoding domain layer class instances, such as BlogPost.

Calling json_encode() with an instance of a class results in a JSON string with a single object. PHP will use the public properties of the class and add them as key-value pairs in the JSON-encoded object.

class BlogPost {
    protected int $Id = 1;
    public string $Title = "Example";
}
 
// produces '{"Title": "Example"}'
$json = json_encode(new BlogPost());

PHP does not automatically access protected or private properties. This standard implementation is therefore insufficient for all classes except the simplest. Instead, your classes can do it JsonSerializable couple. Allows you to control how instances are transformed to JSON.

JsonSerializable defines a single method, jsonSerialize(), which PHP will call when an instance needs to be serialized to JSON:

class BlogPost implements JsonSerializable {
    protected int $Id = 1;
    public string $Title = "Example";
 
    public function jsonSerialize() {
        return [
            "Id" => $this -> Id,
            "Title" => $this -> Title
        ];
    }
}
 
// produces '{"Id": 1, "Title": "Example"}'
$json = json_encode(new BlogPost());

Implement JsonSerializable puts you in control of the serialization process. Your instances can choose what to display, including potentially protected properties, dynamically calculated values, and data returned by method calls.

You don’t even need to return an array. The jsonSerializable method signature specifies a mixed return type so that you can specify any value that PHP can serialize to JSON. You could return another object to have PHP serialize it recursively.


Source link