1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
# Json Serializer for PHP
<p align="center">
<a href="LICENSE.txt" target="_blank">
<img alt="Software License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square">
</a>
<img alt="Build Status" src="https://github.com/zumba/json-serializer/actions/workflows/php.yml/badge.svg?branch=master">
<a href="https://packagist.org/packages/zumba/json-serializer" target="_blank">
<img alt="Total Downloads" src="https://img.shields.io/packagist/dt/zumba/json-serializer.svg?style=flat-square">
</a>
<a href="https://packagist.org/packages/zumba/json-serializer" target="_blank">
<img alt="Latest Stable Version" src="https://img.shields.io/packagist/v/zumba/json-serializer.svg?style=flat-square&label=stable">
</a>
</p>
This is a library to serialize PHP variables in JSON format. It is similar of the `serialize()` function in PHP,
but the output is a string JSON encoded. You can also unserialize the JSON generated by this tool and have you
PHP content back.
Supported features:
- Encode/Decode of scalar, null, array
- Encode/Decode of objects
- Encode/Decode of binary data
- Support nested serialization
- Support not declared properties on the original class definition (ie, properties in `stdClass`)
- Support object recursion
- Closures (via 3rd party library. See details below)
Unsupported serialization content:
- Resource (ie, `fopen()` response)
- NAN, INF constants
Limitations:
- Binary data containing null bytes (\u0000) as array keys cannot be properly decoded because of a json extension bug:
- https://github.com/remicollet/pecl-json-c/issues/7
- https://github.com/json-c/json-c/issues/108
This project should not be confused with `JsonSerializable` interface added on PHP 5.4. This interface is used on
`json_encode` to encode the objects. There is no unserialization with this interface, differently from this project.
*Json Serializer requires PHP >= 7.2 and tested until PHP 8.4*
## Example
```php
class MyCustomClass {
public $isItAwesome = true;
protected $nice = 'very!';
}
$instance = new MyCustomClass();
$serializer = new Zumba\JsonSerializer\JsonSerializer();
$json = $serializer->serialize($instance);
// $json will contain the content {"@type":"MyCustomClass","isItAwesome":true,"nice":"very!"}
$restoredInstance = $serializer->unserialize($json);
// $restoredInstance will be an instance of MyCustomClass
```
## How to Install
If you are using composer, install the package [`zumba/json-serializer`](https://packagist.org/packages/zumba/json-serializer).
```
$ composer require zumba/json-serializer
```
Or add the `zumba/json-serializer` directly in your `composer.json` file.
If you are not using composer, you can just copy the files from `src` folder in your project.
## Serializing Binary Strings
Binary strings introduce two special identifiers in the final json: `@utf8encoded` and `@scalar`.
`@utf8encoded` is an array of keys from the original data which have their value (or the keys themselves)
encoded from 8bit to UTF-8. This is how the serializer knows what to encode back from UTF-8 to 8bit when deserializing.
Example:
```php
$data = ['key' => '<binaryvalue>', 'anotherkey' => 'nonbinaryvalue'];
$serializer = new Zumba\JsonSerializer\JsonSerializer();
$json = $serializer->serialize($data);
// $json will contain the content {"key":"<utf8encodedbinaryvalue>","anotherkey":"nonbinaryvalue","@utf8encoded":{"key":1}}
```
`@scalar` is used only when the value to be encoded is not an array or an object but a binary string. Example:
```php
$data = '<binaryvalue>';
$serializer = new Zumba\JsonSerializer\JsonSerializer();
$json = $serializer->serialize($data);
// $json will contain the content {"@scalar":"<utf8encodedbinaryvalue>","@utf8encoded":1}
```
## Serializing Closure
For serializing PHP closures you can either use [OpisClosure](https://github.com/opis/closure) (preferred) or
[SuperClosure](https://github.com/jeremeamia/super_closure) (the project is abandoned, so kept here for backward
compatibility).
Closure serialization has some limitations. Please check the OpisClosure or SuperClosure project to check if it fits
your needs.
To use the OpisClosure with JsonSerializer, just add it to the closure serializer list. Example:
```php
$toBeSerialized = [
'data' => [1, 2, 3],
'worker' => function ($data) {
$double = [];
foreach ($data as $i => $number) {
$double[$i] = $number * 2;
}
return $double;
}
];
$jsonSerializer = new \Zumba\JsonSerializer\JsonSerializer();
$jsonSerializer->addClosureSerializer(new \Zumba\JsonSerializer\ClosureSerializer\OpisClosureSerializer());
$serialized = $jsonSerializer->serialize($toBeSerialized);
```
You can load multiple closure serializers in case you are migrating from SuperClosure to OpisClosure for example.
PS: JsonSerializer does not have a hard dependency of OpisClosure or SuperClosure. If you want to use both projects
make sure you add both on your composer requirements and load them with `addClosureSerializer()` method.
## Custom Serializers
Some classes may not be suited to be serialized and unserialized using the default reflection methods.
Custom serializers provide the ability to define ```serialize``` and ```unserialize``` methods for specific classes.
```php
class MyType {
public $field1;
public $field2;
}
class MyTypeSerializer {
public function serialize(MyType $obj) {
return array('fields' => $obj->field1 . ' ' . $obj->field2);
}
public function unserialize($values) {
list($field1, $field2) = explode(' ', $values['fields']);
$obj = new MyType();
$obj->field1 = $field1;
$obj->field2 = $field2;
return $obj;
}
}
// map of "class name" => Custom serializer
$customObjectSerializers['MyType'] = new MyTypeSerializer();
$jsonSerializer = new Zumba\JsonSerializer\JsonSerializer(null, $customObjectSerializers);
$toBeSerialized = new MyType();
$toBeSerialized->field1 = 'x';
$toBeSerialized->field2 = 'y';
$json = $jsonSerializer->serialize($toBeSerialized);
// $json == {"@type":"Zumba\\\\JsonSerializer\\\\Test\\\\SupportClasses\\\\MyType","fields":"x y"}
$myType = $jsonSerializer->unserialize($json);
// $myType == $toBeSerialized
```
|