Coder Social home page Coder Social logo

zumba / json-serializer Goto Github PK

View Code? Open in Web Editor NEW
125.0 125.0 23.0 173 KB

Serialize PHP variables, including objects, in JSON format. Support to unserialize it too.

Home Page: http://tech.zumba.com/2014/01/06/json-serializer/

License: MIT License

PHP 100.00%

json-serializer's People

Contributors

aramonc avatar cjsaylor avatar ghola avatar jrbasso avatar marcimat avatar mauriciofauth avatar maxgfeller avatar przemyslaw-bogusz avatar sourceguardian avatar williamdes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-serializer's Issues

PHP 7.1: Fatal error: Dynamic class names are not allowed in compile-time ::class fetch

Thank you for this nice light-weight library - I use it a lot for testing purposes πŸ‘

With version 3.1.0, serialization has stopped working under PHP 7.1 due to using an unsupported feature:

Fatal error: Dynamic class names are not allowed in compile-time ::class fetch in zumba/json-serializer/src/JsonSerializer/JsonSerializer.php on line 266

'::class' on objects is only allowed since PHP 8.0

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, ".", "" ) . ')';
            }

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

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 ?

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.

`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.

PHP 7.1 added support for more precise float encoding in json_encode

Not sure the best way to add this while supporting backwards compatibility.
https://wiki.php.net/rfc/precise_float_value

This test fails in PHP7.1+:

$data = [1.0, 1.1, 0.00000000001, 1.999999999999, 223423.123456789, 1e5, 1e11];
$expected = '[1.0,1.1,1.0e-11,1.999999999999,223423.12345679,100000.0,100000000000.0]';
$this->assertSame($expected, $this->serializer->serialize($data));
1) Zumba\JsonSerializer\Test\JsonSerializerTest::testSerializeFloatLocalized
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-[1.0,1.1,1.0e-11,1.999999999999,223423.12345679,100000.0,100000000000.0]
+[1.0,1.1,1.0e-11,1.999999999999,223423.123456789,100000.0,100000000000.0]

Support of UnitEnum and BackedEnum unserialization for PHP 8.1+

Hi,

Both Enum types can’t be deserialized and create a fatal error : Fatal error: Uncaught Error: Cannot instantiate enum ...

I think they could be both managed into unserializeObject method by adding :

if (is_subclass_of($className, \BackedEnum::class) || is_subclass_of($className, \UnitEnum::class)) {
    return constant("$className::{$value['name']}");
}

Hope it helps :)

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"}

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

Non UTF-8 Characters

There is a problem with Non UTF-8 Characters.
Anything Non UTF-8 being passed to the json_encode throws warnings.

Deprecated when unserializing a DateTimeImmutable object on PHP 8.2

Hi

Some deprecated are shown when unserializing a DateTimeImmutable object, like :

Creation of dynamic property DateTimeImmutable::$date is deprecated (in JsonSerializer.php on line 463)

I think this could be treated like DateTime object, on unserializeObject() method like

        if ($className === 'DateTime' || $className === 'DateTimeImmutable') {
            $obj = $this->restoreUsingUnserialize($className, $value);
            $this->objectMapping[$this->objectMappingIndex++] = $obj;
            return $obj;
        }

Hope it helps :)

Make more flexible to customize unserialization of classes

We currently have a special condition for DateTime class, but looking at the project forks people are also extending it MongoId and MongoDate. Having an easier way to customize it would be ideal to avoid forks and customization diverging the project.

An idea would be making JsonSerializer receive a list of classname with callable to generate the output. It would be used on the unserialize portion. The current DateTime customization would live in this project since it is a php-core class. People could add it on demand.

Update docs to explain how to implement these customizations too and how to use.

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.