In this page:
- Introduction
- Library Structure
- Usage Example
- Adding Extra Properties
- Working With Arrays
- Working With Objects
- Converting JSON String to Json Object
- Properties Style
- Reading JSON File
- PHP 8 Attributes for Serialization
- Typed Deserialization
- Converting to Array
- Converting to JSONx
When designing web services, the developer must decide on the response format at which the server will send back to the client after processing the request. One of the most widely used formats is called JSON. PHP does provide functions for encoding and decoding JSON using the methods json_encode(). And json_decode() but the two have some limitations. Since the framework promots the use of OOP approach, it uses a library called WebFiori Json to create well formatted JSON output.
Note: This library can be included using composer by including this entry in the
requirepart of thecomposer.jsonfile:"webfiori/jsonx":"*".
In most cases, the developer will have to use one class and one interface. The class Json is the core of the library. This class is the one which is used to create the final JSON and JSONx output. In addition to that, it can be used to parse JSON strings and convert them to Json objects.
The interface JsonI can be used to customize JSON and JSONx representation of objects which implement it when encoded. The interface has only one method which is JsonI::toJSON().
The following code sample shows the most basic use case. It simply shows how to add a set of key/value pairs to be represented as JSON.
use WebFiori\Json\Json;
$jsonObj = new Json([
'first-name' => 'Ibrahim',
'last-name' => 'BinAlshikh',
'age' => 26,
'is-married' => true,
'mobile-number' => null
]);The JSON output that will be generated by the given code will be similar to the following JSON:
{
"first-name":"Ibrahim",
"last-name":"BinAlshikh",
"age":26,
"is-married":true,
"mobile-number":null
}In addition to initializing your data using the constructor, it is possible to add more properties using one of the methods which can be used to add extra properties.
The method Json::add() can be used to add numbers, strings or objects, etc... to your JSON.
$jsonObj = new Json();
$jsonObj->add('first-name', 'Ibrahim');
$jsonObj->add('number', 45);
$jsonObj->add('another-number', 1.667);
$jsonObj->add('boolean', true);
$jsonObj->add('array', ['hello', 77, 88]);
$jsonObj->add('another-array', ['Bad', null, false]); {
"first-name":"Ibrahim",
"number":45,
"another-number":1.667,
"boolean":true,
"array":[
"hello",
77,
88
],
"another-array":[
"Bad",
null,
false
]
}You can add multiple properties at once using the addMultiple() method:
$jsonObj = new Json();
$jsonObj->addMultiple([
'user-id' => 123,
'username' => 'john_doe',
'email' => 'john@example.com',
'is-active' => true,
'roles' => ['user', 'editor'],
'profile' => [
'first-name' => 'John',
'last-name' => 'Doe',
'age' => 30
]
]);You can access and modify properties after creation:
$jsonObj = new Json(['name' => 'Ibrahim', 'age' => 26]);
// Get a property value
$name = $jsonObj->get('name');
// Check if property exists
if ($jsonObj->hasKey('age')) {
echo "Age property exists";
}
// Remove a property
$jsonObj->remove('age');
// Get all properties as array
$allProps = $jsonObj->getPropsNames();In addition to the method Json::add(), there are other methods which are specific for adding specific types:
Json::addArray(). Used to add arrays.Json::addBoolean(). Used to add boolean value (trueorfalse).Json::addNumber(). Used to add numbers (integers or floats).Json::addObject(). Used to add PHP objects.
Arrays in PHP language can be associative, indexed or a mix of the two. When adding arrays to an instance of Json, the array can be added as an object or an array. This can be useful if the developer would like to convert an associative array to JSON object. The following code shows how the array will appear if added as indexed array.
$jsonObj = new Json();
$arr = [
"one",
"two",
"assoc" => "ok"
];
$jsonObj->addArray("array", $arr);The JSON that will be generated by the given code will be similar to the following:
{
"array":[
"one",
"two",
"ok"
]
}In order to add the array as object, the developer must include extra parameter which tells the library to convert the array to JSON object when encoded.
$jsonObj = new Json();
$arr = [
"one",
"two",
"assoc" => "ok"
];
$jsonObj->addArray("array", $arr, true);The JSON that will be generated by the given code will be similar to the following:
{
"array":{
"0":"one",
"1":"two",
"assoc":"ok"
}
}More details about this feature can be found in the next section.
It is possible to add arrays as objects to Json instance. This can be achieved using last parameter of the method Json::add(). Another option is to supply true for the last argument if the method Json::addArray() is used.
Note that if the index is associative, its key will be used as property name. If the array is indexed, the names of the properties will be numbers.
Note: If the array has sub-arrays and is added as object, sub arrays will also be added as objects.
$jsonObj = new Json();
$arr = ["one", "two", 3, 3.5, "hello"];
$jsonObj->addArray("array", $arr, true);{
"array": {
"0": "one",
"1": "two",
"2": 3,
"3": 3.5,
"4": "hello"
}
}$jsonObj = new Json();
$arr = [
"one"=>1,
"two"=>2,
"assoc" => "ok"
];
$jsonObj->add("array", $arr, [
'array-as-object' => true
]);{
"array": {
"one": 1,
"two": 2,
"assoc": true
}
}$jsonObj = new Json();
$arr = [
"hello" => "World",
"first-name" => "Ibrahim",
"Random String",
33,
null,
true,
'is-good' => true,
500
];
$jsonObj->addArray("array", $arr, true);{
"array": {
"hello": "World",
"first-name": "Ibrahim",
"0": "Random String",
"1": 33,
"2": null,
"3": true,
"is-good": true,
"4": 500
}
}It is possible to add any object to an instance of Json but there is a catch here. If the object does not implement the interface JsonI, then the properties that will be added will depend on the public get methods of the object.
Assuming that we would like to add an instance of the following class to an instance of Json:
class Employee {
private $fName;
private $lName;
private $salary;
public function __construct($fName, $lName, $salary) {
$this->fName = $fName;
$this->lName = $lName;
$this->salary = $salary;
}
public function getFirstName() {
return $this->fName;
}
public function getLastName() {
return $this->lName;
}
public function getFullName() {
return $this->getFirstName().' '.$this->getLastName();
}
public function salary() {
return $this->salary;
}
}Also, assuming that we add the object as follows:
$jsonObj = new Json();
$jsonObj->addObject("obj", new Employee("Ibrahim", "BinAlshikh", 7200));The JSON output that will be created will be similar to the following:
{
"obj": {
"FirstName": "Ibrahim",
"LastName": "BinAlshikh",
"FullName": "Ibrahim BinAlshikh"
}
}What happened here is the following, the method Json::addObject() will try to access the public methods of the instance. After that, it will search for the methods that has the prefix get in their name. Based on that, it will detect the name of the property. If the name of the method is getFirstName, the name of the property will be FirstName.
Note: The final name of the property will depend on the style of the properties names. For example, if properties style is set to
snake, then the name of the propertyLastNamewould belast_name.
The interface JsonI is used to customize the generated JSON output of an object. The interface has one method at which the developer must implement which is JsonI::toJSON(). The developer must implement the method in a way it returns an instance of the class Json.
Assuming that we have the same Employee class from previous example, we can use the interface JsonI to customize JSON output as follows:
use WebFiori\Json\JsonI;
use WebFiori\Json\Json;
class MyClass implements JsonI {
private $fName;
private $lName;
private $salary;
public function __construct($fName, $lName, $salary) {
$this->fName = $fName;
$this->lName = $lName;
$this->salary = $salary;
}
public function getFirstName() {
return $this->fName;
}
public function getLastName() {
return $this->lName;
}
public function getFullName() {
return $this->getFirstName().' '.$this->getLastName();
}
public function salary() {
return $this->salary;
}
public function toJSON() {
return new Json([
'first-name' => $this->getFirstName(),
'last-name' => $this->getLastName(),
'salary' => $this->salary()
]);
}
}JSON output of the given code would be similar to the following:
{
"obj": {
"first-name": "Ibrahim",
"last-name": "BinAlshikh",
"salary": 7200
}
}Here's a more comprehensive example of working with objects:
use WebFiori\Json\JsonI;
use WebFiori\Json\Json;
class Product implements JsonI {
private $id;
private $name;
private $price;
private $categories;
public function __construct($id, $name, $price, $categories = []) {
$this->id = $id;
$this->name = $name;
$this->price = $price;
$this->categories = $categories;
}
public function toJSON() {
return new Json([
'product-id' => $this->id,
'name' => $this->name,
'price' => $this->price,
'categories' => $this->categories,
'formatted-price' => '$' . number_format($this->price, 2)
]);
}
}
// Usage
$product = new Product(1, 'Laptop', 999.99, ['Electronics', 'Computers']);
$jsonObj = new Json();
$jsonObj->addObject('product', $product);The library supports converting JSON-like strings to Json instance. The static method Json::decode() is used to perform that task. This can be useful if the developer would like to add extra properties to JSON input which was sent by a web browser or HTTP client. The following code sample shows how to use the method.
$jsonObj = Json::decode('{"hello":"world","sub-obj":{},"an-array":["First Item"]}');
$jsonObj->get('sub-obj')->addMultiple([
'first-name' => 'Ibrahim',
'last-name' => 'BinAlshikh',
'salary' => 7200
]);
$arr = $jsonObj->get('an-array');
$arr[] = "Second Item";
$jsonObj->add('an-array', $arr);What the code doing is to add properties to the sub-obj and add one extra item to the array an-array. The JSON output will be similar to the following.
{
"hello": "world",
"sub-obj": {
"first-name": "Ibrahim",
"last-name": "BinAlshikh",
"salary": 7200
},
"an-array": [
"First Item",
"Second Item"
]
}It is possible to set a custom style for the properties to use. By default, the style is set to none. In this case, property style will be exactly the same as when it was added. In addition to the none style, the class Json supports 3 styles, snake, kebab and camel.
Setting the style of the properties can be achieved in two ways. The first one is to define a global constant with the name JSON_PROP_STYLE which is a string that has one of the values of the array Json::PROP_NAME_STYLES. If this constant is defined, it will be used by every instance of the class Json.
Another way to set the style is to use the method Json::setPropsStyle(). This method can be used to set specific style for one instance.
$jsonObj = new Json([
'first-prop' => 1,
'SecondProp' => 'Hello',
'Third_prop' => true
]);
$jsonObj->setPropsStyle('snake');The generated output will be similar to the following JSON:
{
"first_prop": 1,
"second_prop": "Hello",
"third_prop": true
}$jsonObj = new Json([
'first-prop' => 1,
'SecondProp' => 'Hello',
'Third_prop' => true
]);
$jsonObj->setPropsStyle('kebab');The generated output will be similar to the following JSON:
{
"first-prop": 1,
"second-prop": "Hello",
"third-prop": true
}$jsonObj = new Json([
'first-prop' => 1,
'SecondProp' => 'Hello',
'Third_prop' => true
]);
$jsonObj->setPropsStyle('camel');The generated output will be similar to the following JSON:
{
"firstProp": 1,
"SecondProp": "Hello",
"ThirdProp": true
}One of the great features of the library is the ability to read any file that contains valid JSON and load it into an object of type Json. To achieve this, the static method Json::fromJsonFile() can be used. This method will return an object of type Json if the file content was parsed without issues. The following code sample shows how to use that method.
$jsonObj = Json::fromJsonFile('jsonData.json');
if ($jsonObj instanceof Json) {
// Do things with the data
} else {
// Failed to read JSON data.
}Customize the JSON key name for a property or getter method:
use WebFiori\Json\JsonProperty;
class User {
#[JsonProperty('user-name')]
public string $username = '';
#[JsonProperty('e-mail')]
public string $email = '';
public int $age = 0;
}
$user = new User();
$user->username = 'ibrahim';
$user->email = 'ibrahim@example.com';
$user->age = 30;
$json = new Json();
$json->addObject('user', $user);Output:
{
"user": {
"user-name": "ibrahim",
"e-mail": "ibrahim@example.com",
"age": 30
}
}Exclude a property or getter from JSON output:
use WebFiori\Json\JsonIgnore;
class User {
public string $name = '';
#[JsonIgnore]
public string $password = '';
public string $email = '';
}The password property will never appear in the JSON output.
The JsonDeserializer class converts JSON data back into typed PHP objects. It supports constructor hydration, setter methods, and public properties.
use WebFiori\Json\Json;
use WebFiori\Json\JsonDeserializer;
class User {
public function __construct(
public string $name = '',
public string $email = '',
public int $age = 0
) {}
}
$json = Json::decode('{"name":"Ibrahim","email":"ibrahim@example.com","age":30}');
$user = JsonDeserializer::deserialize($json, User::class);
echo $user->name; // Ibrahim
echo $user->email; // ibrahim@example.com
echo $user->age; // 30The deserializer resolves values in this order:
- Static
fromJSON(Json $json)factory method (if exists) - Constructor parameters matched by name
- Setter methods (e.g.,
setName()for keyname) - Public properties
For nested objects or arrays of objects, use the #[JsonType] attribute:
use WebFiori\Json\JsonType;
class Address {
public function __construct(
public string $city = '',
public string $country = ''
) {}
}
class Order {
public function __construct(
public int $id = 0,
public string $product = '',
public float $total = 0
) {}
}
class User {
public function __construct(
public string $name = '',
#[JsonType(Address::class)]
public ?Address $address = null,
#[JsonType(Order::class, isArray: true)]
public array $orders = []
) {}
}
$json = Json::decode('{
"name": "Ibrahim",
"address": {"city": "Riyadh", "country": "SA"},
"orders": [
{"id": 1, "product": "Laptop", "total": 999.99},
{"id": 2, "product": "Mouse", "total": 29.99}
]
}');
$user = JsonDeserializer::deserialize($json, User::class);
echo $user->address->city; // Riyadh
echo $user->orders[0]->product; // Laptop
echo count($user->orders); // 2If a class has a static fromJSON() method, it takes priority:
class Config {
private array $data;
private function __construct(array $data) {
$this->data = $data;
}
public static function fromJSON(Json $json): self {
return new self([
'host' => $json->get('db-host'),
'port' => $json->get('db-port') ?? 3306,
]);
}
}
$json = Json::decode('{"db-host":"localhost","db-port":5432}');
$config = JsonDeserializer::deserialize($json, Config::class);The toArray() method converts a Json object to a plain PHP associative array. This avoids the overhead of encoding to a JSON string and decoding it back with json_decode().
use WebFiori\Json\Json;
$json = new Json([
'name' => 'Ibrahim',
'age' => 30,
'active' => true,
]);
$address = new Json(['city' => 'Riyadh', 'country' => 'SA']);
$json->add('address', $address);
$array = $json->toArray();
// Result:
// [
// 'name' => 'Ibrahim',
// 'age' => 30,
// 'active' => true,
// 'address' => [
// 'city' => 'Riyadh',
// 'country' => 'SA',
// ],
// ]The method recursively converts all nested Json objects into associative arrays. Arrays are preserved with their elements recursively converted as well. This is useful when:
- Passing structured data to functions that expect arrays
- Writing PHPUnit assertions with
assertEqualsagainst expected arrays - Merging JSON data with other arrays using
array_merge() - Returning data from controller methods without triggering serializer metadata
Previously, the only way to achieve this was the round-trip approach:
// Old approach (inefficient)
$array = json_decode($json . '', true);
// New approach (direct conversion)
$array = $json->toArray();JSONx is IBM standard for representing JSON as XML tree. The library provides full support for constructing JSONx. In order to get JSONx representation of Json instance, the method Json::toJSONxString() can be used.
$j = new Json(['bool-true' => true, 'bool-false' => false]);
echo $j->toJSONxString();<?xml version="1.0" encoding="UTF-8"?>
<json:object xsi:schemaLocation="http://www.datapower.com/schemas/json jsonx.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx">
<json:boolean name="bool-true">
true
</json:boolean>
<json:boolean name="bool-false">
false
</json:boolean>
</json:object>- Web Services - Use JSON for API responses
- Database Management - Convert database results to JSON
- The Class Response - Send JSON responses
- Sessions Management - Store JSON data in sessions