This is a library to serialize PHP variables in JSON format

Overview

Json Serializer for PHP

Software License Build Status Total Downloads Latest Stable Version

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:

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.0 and tested until PHP 7.4

Example

unserialize($json); // $restoredInstance will be an instance of MyCustomClass">
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.

$ 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:

","anotherkey":"nonbinaryvalue","@utf8encoded":{"key":1}}">
$data = ['key' => '
   
    '
   , 'anotherkey' => 'nonbinaryvalue'];
$serializer = new Zumba\JsonSerializer\JsonSerializer();
$json = $serializer->serialize($data);
// $json will contain the content {"key":"
   
    ","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:

","@utf8encoded":1}">
$data = '
   
    '
   ;
$serializer = new Zumba\JsonSerializer\JsonSerializer();
$json = $serializer->serialize($data);
// $json will contain the content {"@scalar":"
   
    ","@utf8encoded":1}
   

Serializing Closures

For serializing PHP closures you have to pass an object implementing SuperClosure\SerializerInterface. This interface is provided by the project SuperClosure. This project also provides a closure serializer that implements this interface.

Closure serialization has some limitations. Please check the SuperClosure project to check if it fits your needs.

To use the SuperClosure with JsonSerializer, just pass the SuperClosure object as the first parameter on JsonSerializer constructor. Example:

$toBeSerialized = array(
	'data' => array(1, 2, 3),
	'worker' => function ($data) {
		$double = array();
		foreach ($data as $i => $number) {
			$double[$i] = $number * 2;
		}
		return $double;
	}
);

$superClosure = new SuperClosure\Serializer();
$jsonSerializer = new Zumba\JsonSerializer\JsonSerializer($superClosure);
$serialized = $jsonSerializer->serialize($toBeSerialized);

PS: JsonSerializer does not have a hard dependency of SuperClosure. If you want to use both projects make sure you add both on your composer requirements.

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.

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">
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
Comments
  • Manage other mode for extra attributes

    Manage other mode for extra attributes

    First, thanks for your effective and simple to use library.

    During unserialization if a property does not exist on target object : the JsonSerializer will try to set an extra attribute to object

    try {
        $propRef = $ref->getProperty($property);
        $propRef->setAccessible(true);
        $propRef->setValue($obj, $this->unserializeData($propertyValue));
    } catch (ReflectionException $e) {
        $obj->$property = $this->unserializeData($propertyValue);
    }
    

    We should manage other mode ($extraAttributeManagementMode):

    • JsonSerializer::EXTRA_ATTRIBUTE_MANAGEMENT_MODE_SET : actual mode
    • JsonSerializer::EXTRA_ATTRIBUTE_MANAGEMENT_MODE_IGNORE : we ignore the json value
    • JsonSerializer::EXTRA_ATTRIBUTE_MANAGEMENT_MODE_EXCEPTION : throw a dedicate exception
    opened by benito103e 6
  • Changed namespace

    Changed namespace

    Moving the namespace from Zumba\Util to a namespace just for the project (Zumba\JsonSerializer). I am planning to add more classes, interfaces and traits, which will add things that are not necessarily part of the Util namespace.

    Also, other open source projects that we have also have dedicated namespaces.

    PS: The JsonSerializer class is the same, just changing the namespace at the top and the exception namespace. It is just how GitHub shows the file change. On the repo it was a file rename.

    opened by jrbasso 6
  • Serialization of internal classes

    Serialization of internal classes

    Serializer throws ReflectionException when class property is an internal class. (For example DateTime class can not be serialized because of this error)

    ReflectionClass::newInstanceWithoutConstructor on php.net

    As a temporary solution I've added a if ($ref->isInternal()) check with newInstance method and it seems to work fine.

    Do you have any other ideas on how to fix the problem?

    bug 
    opened by eymengunay 6
  • Updated up to the current standards + DateTime family classes support

    Updated up to the current standards + DateTime family classes support

    Please take some time to review this. I'm open for discussion any time

    Nothing has been broken, but there's a few changes here and there. :)

    Oh and thanks for open-sourcing this!

    opened by nilportugues 5
  • Added supported classes guard

    Added supported classes guard

    We added the ability to give the engine an explicit list of classes allowed to be serialized/unserialized. It is off by default but can be added via withSupportedClasses() which takes an array of class names and checked via isClassSupported() which takes a single string.

    If withSupportedClasses() is never called then isClassSupported() will always return true.

    Our use-case for this is to make sure that sensitive objects that might be deeply nested in other objects don't get serialized accidentally.

    Although we don't do this, we could also imagine someone storing json in a potentially hostile location so the unserializeObject() also calls isClassSupported() before unserializing.

    opened by cjhaas 4
  • Small json_encode() improvement suggestion

    Small json_encode() improvement suggestion

    Instead of wasting CPU cycles in JsonSerializer::calculateEncodeOptions(), just use numeric value.

    1856 == JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION

    or

    1344 == JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION

    enhancement 
    opened by AnrDaemon 4
  • DateTime serialization does not work in PHP 7.4

    DateTime serialization does not work in PHP 7.4

    To reproduce:

    $serializer = new \Zumba\JsonSerializer\JsonSerializer();
    echo $serializer->serialize(new \DateTime()) . "\n";
    echo $serializer->serialize(new \DateTimeImmutable()) . "\n";
    

    Expected output (as in PHP up to 7.3):

    {"@type":"DateTime","date":"2020-06-11 19:20:05.099012","timezone_type":3,"timezone":"Europe\/Berlin"}
    {"@type":"DateTimeImmutable","date":"2020-06-11 19:20:05.099087","timezone_type":3,"timezone":"Europe\/Berlin"}
    

    Actual output (in PHP 7.4.5):

    {"@type":"DateTime"}
    {"@type":"DateTimeImmutable"}
    
    opened by tsufeki 2
  • Add composer test script

    Add composer test script

    Composer gives us the possibility to define scripts in the composer.json file: Documentation on getcomposer.org

    Most libraries now define a test script which makes running unit tests as easy as executing composer test.

    Here is more on the topic:

    • http://maxgfeller.com/blog/2014/07/22/composer-test/
    • https://pantheon.io/blog/writing-composer-scripts
    opened by MaxGfeller 2
  • Dealing with non UTF8 data

    Dealing with non UTF8 data

    I believe the serializer should be able to handle non UTF8 data. Using a serializer in a messaging system should not limit the type of data you throw at it: what goes in on one side should come out exactly like that on the other side.

    I am currently implementing this feature making heavy use of the mbstring extension (for detecting the string encoding and doing conversions). The idea is that whenever I encounter a string that is not UTF8 encoded, I assume it as being with 8bit encoding, convert it to UTF8 on serialization and then convert it back from UTF8 to 8bit during deserialization. This way, if junk comes in, junk comes out without any modifications.

    In principle, would you accept such a pull request, or do you have a different vision regarding the capabilities of this library? I'm asking because if you are not interested in this feature I will prefer to internalize this library (a refactored version of it) into my project instead of building it onto the existing code.

    opened by ghola 2
  • Throwing exception if cannot encode JSON when serializing

    Throwing exception if cannot encode JSON when serializing

    Hiding encoding errors under the rug is dangerous. We use the serializer in a messaging system and we had a hard time finding out why our messages had empty payloads.

    opened by ghola 2
  • setlocale() issue for floats

    setlocale() issue for floats

    When you change the locale (using, for example, setlocale(LC_ALL, "fr_FR") in your PHP code), the conversion of floats are made in the locale (for France, using "," instead of "." for decimal point). Then if the variable $preserveZeroFractionSupport is set to true, there is an encoding issue.

    I found this workaround forcing the formatting only in specific cases:

                if (!$this->preserveZeroFractionSupport && is_float($value) && abs($value) < 1e+10 && abs($value) > 0.01 ) {
                    // Because the PHP bug #50224, the float numbers with no
                    // precision numbers are converted to integers when encoded
                    // Notice the following will not be sensible to locale.
                    $value = static::FLOAT_ADAPTER . '(' . number_format($value, 6, ".", "" ) . ')';
                }
    
    opened by wrey75 2
  • `SuperClosure\SerializerInterface` is deprecated.

    `SuperClosure\SerializerInterface` is deprecated.

    Description When I implement the readme example of Serializing Closures on PHP 8.1.12, I get this ErrorException.

    SuperClosure\SerializableClosure implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary)

    Does it need to change the depency of SuperClosure to Opis Closure (Maybe the superClosure repo is no longer maintained) to support the closures requirement?

    Thanks.

    opened by ping-yee 0
  • Migrate from superclosure to opis/closure lib

    Migrate from superclosure to opis/closure lib

    jeremeamia/superclosure is being used on the project and it is abandoned. We should use https://packagist.org/packages/opis/closure instead.

    To avoid issues with stored data, the code must support both libraries, where the unserialize can read for either library, but the serialize only writes using the new closure library.

    opened by jrbasso 0
  • parent private property with getter

    parent private property with getter

    when I have:

    <?php
    declare(strict_types=1);
    
    namespace App\Model;
    
    
    abstract class AbstractModel // This need not be a abstract
    {
        private $abstractPrivateProperty;
    
        public $abstractPublicProperty;
    
        protected $abstractProtectedProperty;
    
        public function __construct()
        {
            $this->abstractPrivateProperty = 'private';
            $this->abstractPublicProperty = 'public';
            $this->abstractProtectedProperty = 'protected';
        }
    
        /**
         * @return string
         */
        public function getAbstractPrivateProperty(): string
        {
            return $this->abstractPrivateProperty;
        }
    }
    
    
    class MainModel extends AbstractModel
    {
        public $publicProperty;
    
        private $privateProperty;
    
        protected $protectedProperty;
    
        public function __construct()
        {
            $this->publicProperty = 'public';
            $this->privateProperty = 'private';
            $this->protectedProperty = 'protected';
    
            parent::__construct();
        }
    }
    

    and then I try:

    <?php
    require_once __DIR__ . '/vendor/autoload.php';
    
    $model = new \App\Model\MainModel();
    var_dump($model->getAbstractPrivateProperty()); // returns string(7) "private"
    
    $serializer = new \Zumba\JsonSerializer\JsonSerializer();
    $serialized = $serializer->serialize($model);
    var_dump($serialized); // returns string(193) "{"@type":"App\\Model\\MainModel","publicProperty":"public","privateProperty":"private","protectedProperty":"protected","abstractPublicProperty":"public","abstractProtectedProperty":"protected"}"
    
    /** @var \App\Model\MainModel $back */
    $back = $serializer->unserialize($serialized);
    var_dump($back);
    /** returns
    class App\Model\MainModel#11 (6) {
      public $publicProperty =>
      string(6) "public"
      private $privateProperty =>
      string(7) "private"
      protected $protectedProperty =>
      string(9) "protected"
      private $abstractPrivateProperty =>
      NULL
      public $abstractPublicProperty =>
      string(6) "public"
      protected $abstractProtectedProperty =>
      string(9) "protected"
    }
    */
    var_dump($back->getAbstractPrivateProperty()); // PHP Fatal error:  Uncaught TypeError: Return value of App\Model\AbstractModel::getAbstractPrivateProperty() must be of the type string, null returned
    

    so method getAbstractPrivateProperty returns null after unserialize.

    I think its, bug or not ?

    bug 
    opened by JanGalek 4
  • Refactoring for SOC

    Refactoring for SOC

    Normalizing/denormalizing (converting from object to/from array) and encoding/decoding (converting from array to/from string) are separate concerns. With the introduction of support for binary data the code inflated by quite a bit and has become had to manage. As such, I opted to follow the pattern used in the Symfony Serializer when I refactored the serializer to be used in my library. Here are the three main files that resulted:

    1. ObjectNormalizer deals only with transforming an object to and from an array.
    2. JsonEncoder deals with the actual json encoding/decoding, binary data encoding/decoding, and zero fraction support.
    3. JsonSerializer just uses the previous two.

    In my code I stripped out the bit of functionality that deals with scalars because I'm only dealing with objects, but you get the point.

    It wouldn't be a great effort to apply the same to zumba/json-serializer, but it would break BC compatibility so it would need to bump to version 3.x. You could also consider transforming this library to leverage the Symfony Serializer and just implement an encoder and a normalizer for it. This could potentially open a larger user base for it, as IMO the current normalizers used by the Symfony Serializer are useless.

    What do you think?

    opened by ghola 3
Releases(3.0.2)
JSONFinder - a library that can find json values in a mixed text or html documents, can filter and search the json tree, and converts php objects to json without 'ext-json' extension.

JSONFinder - a library that can find json values in a mixed text or html documents, can filter and search the json tree, and converts php objects to json without 'ext-json' extension.

Eboubaker Eboubaker 2 Jul 31, 2022
Preferences are configuration variables that are user-managed for which we cannot rely upon container parameters or environment variables.

Preferences Preferences are configuration variables that are meant to be user managed for which we cannot rely upon container parameters or environmen

Makina Corpus 1 Feb 7, 2022
Serialize closures. Not maintained. Consider using opis/closure.

PHP SuperClosure A PHP Library for serializing closures and anonymous functions. No Longer Maintained This software is no longer maintained. Consider

Jeremy Lindblom 1.7k Dec 30, 2022
It's MX Player API gives All Content in JSON format

?? MXPlayer API ?? ?? MXPlayer API Can get Streaming URLs and Other Data in JSON Format From mxplayer.in links for Streaming ?? How to Use : ?? Method

Techie Sneh 8 Nov 30, 2021
Here is an Instagram Guest API. Gather all public information as JSON format without logging yourself.

Here is an Instagram Guest API. Gather all public information as JSON format without logging yourself. It's all automation and time saving.

Quatrecentquatre 1 Nov 2, 2021
A simple library to increase the power of your environment variables.

Environment A simple library (with all methods covered by php unit tests) to increase the power of your environment variables, contribute with this pr

João Paulo Cercal 56 Feb 8, 2022
Find undefined and unused variables with the PHP Codesniffer static analysis tool.

PHP_CodeSniffer VariableAnalysis Plugin for PHP_CodeSniffer static analysis tool that adds analysis of problematic variable use. Warns if variables ar

Payton Swick 116 Dec 14, 2022
Find forgotten variables dump in PHP source code.

PHP VarDump Check This repository is abandoned. Suggested alternative: https://github.com/php-parallel-lint/PHP-Var-Dump-Check PHP console application

Jakub Onderka 27 Jul 13, 2022
Find forgotten variables dump in PHP source code.

PHP VarDump Check PHP console application for find forgotten variable dump. Support PHP build in method print_r, var_dump and var_export method and al

PHP Parallel lint 13 Jul 13, 2022
Allows generate class files parse from json and map json to php object, including multi-level and complex objects;

nixihz/php-object Allows generate class files parse from json and map json to php object, including multi-level and complex objects; Installation You

zhixin 2 Sep 9, 2022
Json-normalizer: Provides generic and vendor-specific normalizers for normalizing JSON documents

json-normalizer Provides generic and vendor-specific normalizers for normalizing JSON documents. Installation Run $ composer require ergebnis/json-nor

null 64 Dec 31, 2022
PDF API. JSON to PDF. PDF Template Management, Visual HTML Template Editor and API to render PDFS by json data

PDF Template Management, Visual HTML Template Editor and API to render PDFS by json data PDF ENGINE VERSION: development: This is a prerelease version

Ajous Solutions 2 Dec 30, 2022
A pure PHP implementation of the MessagePack serialization format / msgpack.org[PHP]

msgpack.php A pure PHP implementation of the MessagePack serialization format. Features Fully compliant with the latest MessagePack specification, inc

Eugene Leonovich 368 Dec 19, 2022
A PHP component to convert HTML into a plain text format

html2text html2text is a very simple script that uses DOM methods to convert HTML into a format similar to what would be rendered by a browser - perfe

Jevon Wright 423 Dec 29, 2022
A PHP wrapper around Libreoffice for converting documents from one format to another.

Document Converter A PHP wrapper around Libreoffice for converting documents from one format to another. For example: Microsoft Word to PDF OpenOffice

Lukas White 0 Jul 28, 2022
AnsibleBoy aims to use the Asnible `facts` as data, which can then be visualized in a table format

AnsibleBoy - Ansible Frontend Hub About AnsibleBoy aims to use the Ansible facts as data, which can then be visualized as a table ToDo (note that this

Ron 23 Jul 14, 2022
A proof-of-concept parser for the SMART Health Cards format.

SMART Health Cards parser A proof-of-concept parser for the SMART Health Cards format. This is not intended for production use. I just hacked this tog

Mikkel Paulson 55 Jul 31, 2022
Laravel package to convert English numbers to Bangla number or Bangla text, Bangla month name and Bangla Money Format

Number to Bangla Number, Word or Month Name in Laravel | Get Wordpress Plugin Laravel package to convert English numbers to Bangla number or Bangla te

Md. Rakibul Islam 50 Dec 26, 2022
Tool for easy selection and export of user files in ZIP format.

Personal data export Idea Tool for easy selection and export of user files in ZIP format. Within a single selector, you choose all user data (much of

Baraja packages 2 Oct 18, 2021