项目作者: realshadow

项目描述 :
PHP collection of serializers for JSON, JSONP, XML, YAML, INI
高级语言: PHP
项目地址: git://github.com/realshadow/serializers.git
创建时间: 2015-07-29T21:44:33Z
项目社区:https://github.com/realshadow/serializers

开源协议:MIT License

下载


PHP collection of serializers for JSON, JSONP, XML, YAML, INI

Written for PHP 5.3 to solve a specific issue - singularization/pluralization of elements when transforming them from and to arrays. The difference between serializers was obvious when we passed XML files between PHP, Python and .NET. Later, more serializers were added to get a complete package.

The goal was to automatically perform singularization of arrays when serializing to XML. E.g.

  1. array(
  2. 'products' => array(
  3. array(
  4. 'brand' => 'Samsung',
  5. 'model' => 'Galaxy',
  6. 'price' => 999
  7. ),
  8. array(
  9. 'brand' => 'HTC',
  10. 'model' => 'One',
  11. 'price' => null
  12. )
  13. )
  14. );

Which, when serialized, would become

  1. <products>
  2. <product>
  3. <brand>Samsung</brand>
  4. <model>Galaxy</model>
  5. <price>999</price>
  6. </product>
  7. <product>
  8. <brand>HTC</brand>
  9. <model>One</model>
  10. <price xsi:nil="true"></price>
  11. </product>
  12. </products>

instead of (this is the default behaviour)

  1. <products>
  2. <brand>Samsung</brand>
  3. <model>Galaxy</model>
  4. <price>999</price>
  5. </products>
  6. <products>
  7. <brand>HTC</brand>
  8. <model>One</model>
  9. <price xsi:nil="true"></price>
  10. </products>

Same rule applies to deserialization which, by using different serializers, would turn into into different arrays. By applying singularization the other way around, it is possible to get back the same array as was used for serialization.

XML Serialization

Support for

  • attributes, namespaces, cdata and comments
  • singularization of words - products => product
  • option to automatically add xsi:nil=true to null elements
  • event for manipulation of nodes
  1. $array = array(
  2. Serializers\Encoders\Xml::ATTRIBUTES => array(
  3. 'xmlns' => 'http://cfh.sk/izmluvnik/xsell',
  4. Serializers\Encoders\Xml::NS => array(
  5. array(
  6. 'name' => 'xmlns:xsi',
  7. 'content' => 'http://www.w3.org/2001/XMLSchema-instance'
  8. ),
  9. array(
  10. 'name' => 'xmlns:xsd',
  11. 'content' => 'http://www.w3.org/2001/XMLSchema'
  12. )
  13. )
  14. ),
  15. 'products' => array(
  16. array(
  17. 'brand' => 'Samsung',
  18. 'model' => 'Galaxy',
  19. 'price' => 999
  20. ),
  21. array(
  22. 'brand' => 'HTC',
  23. 'model' => 'One',
  24. 'price' => null
  25. )
  26. )
  27. );
  28. $xml = Serializers\Encode::toXml('root', $array, array(
  29. 'singularize_words' => true,
  30. 'nil_on_null' => true
  31. ));
  32. print $xml->withHeaders();

Which outputs

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <root xmlns="http://cfh.sk/izmluvnik/xsell" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  3. <products>
  4. <product>
  5. <brand>Samsung</brand>
  6. <model>Galaxy</model>
  7. <price>999</price>
  8. </product>
  9. <product>
  10. <brand>HTC</brand>
  11. <model>One</model>
  12. <price xsi:nil="true"></price>
  13. </product>
  14. </products>
  15. </root>

XML Deserialization

By default every comment, attribute, namespace will be stripped from the result as well as
the root element. Every option can be turned off/on in config

Deserialization is done by SimpleXML coupled with json_encode (in this case provided JSON decoder) with one
simple addition - SimpleXML object will be transformed before being encoded with json_encode (backport of
JSONSerialize interface)

Comments are parsed separately via DOMXpath (since SimpleXML can not handle them) and are
added to a separate array with indexes poiting to their original location, with that, it should
be easy to merge comments with the main result and receive the original array.

By default, transforming elements from their singular counterpart back to plural and thus
flattening the whole array is turned off and must be turned on. Its possible to both - include
new mappings for words and to exclude specific words. This works exactly as in provided XML
encoder.

The whole goal of flattening is to get back exactly the same array as the one that was used
to create provided XML.

  1. // using the same XML that we got in serialization
  2. $output = Serializers\Decode::xml($xml->load(), array('singularize_words' => true));

Which outputs exactly the same array as was used in the example before

  1. print_r($output->toArray());

JSON Deserialization

Support for:

  • automatic parsing of Microsoft’s JSON date format (e.g. /Date(1425556377427+0100)/)
  • backport of JSON_BIGINT_AS_STRING available from PHP 5.4.0
  • isValid method for checking validity of provided JSON string
  • possible conversion from JSON to:
    • PHP types (string, array, object)
    • XML, YAML, INI

With overriding configuration one can change the default timeformat and timezone settings form MS date conversion, or turn it off completely.

It’s possible to register an event callback to be called during escaping of BIGINT, in case said escaping is not good enough, or to turning it off completely.

Callback method must accept one parameter and thats registered JSON string. Callback can be a closure or anything else that will pass as callable.

  1. $json = <<<EOT
  2. {
  3. "foo" : "bar",
  4. "small" : "123456",
  5. "large" : 200000000000009093302,
  6. "text" : "Example ratio 1000000000000000:1",
  7. "date" : "/Date(1425556377427+0100)/"
  8. }
  9. EOT;
  10. $s = Serializers\Decode::json($json);
  11. print_r($s->toObject());
  12. // transform said json to xml and output it
  13. print Serializers\Decode::json($json)->toXml('root')->withHeaders();
  14. // events
  15. $json = Serializers\Decode::json($json)->on(Serializers\Events::JSON_MSDATE_MATCH, function($date) {
  16. // matches returned from preg_replace_callback
  17. list(, $timestamp,,) = $date;
  18. return date('Y-m-d H:i:s', $timestamp);
  19. });

JSON Serialization

It is possible to register JSON_SERIALIZE event that works exactly like PHP 5.4 JsonSerializable interface and thus allows modifying the object before it is converted to JSON.

JSON Serializer also includes a method for creating dates in Microsoft JSON date format, e.g /Date(1425556377427+0100)/

  1. $json = Serializers\Encode::toJson(array(
  2. 'foo' => 'bar',
  3. 'foodate' => date('d.m.Y H:i:s')
  4. ))->onSerialize(function($data) {
  5. $data['foodate'] = Serializers\Encoders\Json::toMSDate($data['foodate']);
  6. return $data;
  7. });
  8. print $json->withHeaders();

JSONP Serialization

Class for easy JSONP serialization, behaves like JSON serializer with additional checks for callback function name validation, which can be changed with custom event

  1. $jsonp = Serializers\Encode::toJsonp('_foo.bar', array(
  2. 'foo' => 'bar',
  3. 'bar' => 'foo'
  4. ));
  5. $jsonp->allowCors('*', array('GET', 'POST'));
  6. print $jsonp->withHeaders();

JSONP Deserialization

Class for easy JSONP deserialization, behaves like JSON deserializer

  1. $json = '_foo.bar({"foo":"bar","bar":"foo"})';
  2. $data = Serializers\Decode::jsonp($json);
  3. print_r($data->toObject());
  4. // transform said json to xml with callback name as root element and output it
  5. print Serializers\Decode::jsonp($json)->toXml()->withHeaders();

YAML Serializer

Uses Symfony’s YAML component under the hood

  1. $yaml = \Serializers\Encode::toYaml($array);
  2. print_r($yaml->load());
  3. // or
  4. $yaml->toFile('config.yml');

YAML Deserializer

Uses Symfony’s YAML component under the hood.

Transformation to XML, JSON, etc. is possible, but is subjected to the possibilities of the YAML converter.

  1. $yaml = Serializers\Decode::yaml(file_get_contents('config.yml'));
  2. print_r($yaml->toObject());
  3. // transform said json to xml and output it
  4. print Serializers\Decode::yaml(file_get_contents('config.yml'))->toXml('yaml')->withHeaders();

INI Deserializer

Uses INI parser by @austinhyde

  1. $array = array(
  2. 'a' => 'd',
  3. 'b' => array('test' => 'c'),
  4. 'database' => array(
  5. 'default' => array(
  6. 'name' => 'db',
  7. 'host' => 'master.db',
  8. 'ip' => 'dd',
  9. )
  10. ),
  11. 'array' => array('a', '1', 3),
  12. );
  13. $encode = Serializers\Encode::toIni($array);
  14. $encode->toFile('config.ini');

INI Serializer

The functionality is limited to basic INI formats, e.g. no support for inheritance. As I can’t see a good use case at the moment, this class is here only for keeping a complete stack of encoders/decoders together

  1. $ini = Serializers\Encode::toIni($array);
  2. print_r($ini->load());