Created
June 7, 2019 09:04
-
-
Save jenschude/87895b4b71ac71609d59d0f0bcba14d3 to your computer and use it in GitHub Desktop.
JsonReader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require __DIR__ . '/../vendor/autoload.php'; | |
use Doctrine\Common\Annotations\AnnotationRegistry; | |
use JMS\Serializer\Annotation as Serializer; | |
use JMS\Serializer\Annotation\Type; | |
use JMS\Serializer\SerializerBuilder; | |
use pcrov\JsonReader\JsonReader; | |
AnnotationRegistry::registerLoader('class_exists'); | |
$json = <<<'JSON' | |
{ | |
"type": "donut", | |
"name": "Cake", | |
"test": { | |
"type": "donut", | |
"name": "Cake" | |
}, | |
"toppings": [ | |
{ "id": 5002, "type": "Glazed" }, | |
{ "id": 5006, "type": "Chocolate with Sprinkles" }, | |
{ "id": 5004, "type": "Maple" } | |
] | |
} | |
JSON; | |
class Toppings { | |
/** | |
* @Type("int") | |
*/ | |
private $id; | |
/** | |
* @Type("string") | |
*/ | |
private $type; | |
/** | |
* @param mixed $id | |
*/ | |
public function setId($id) | |
{ | |
$this->id = $id; | |
} | |
/** | |
* @param mixed $type | |
*/ | |
public function setType($type) | |
{ | |
$this->type = $type; | |
} | |
} | |
class Donut { | |
/** | |
* @Type("string") | |
*/ | |
private $type; | |
/** | |
* @Type("string") | |
*/ | |
private $name; | |
/** | |
* @Type("Toppings") | |
*/ | |
private $toppings; | |
/** | |
* @Type("Donut") | |
*/ | |
private $test; | |
/** | |
* @param mixed $test | |
*/ | |
public function setTest($test) | |
{ | |
$this->test = $test; | |
} | |
public function setType($type) | |
{ | |
$this->type = $type; | |
} | |
/** | |
* @param mixed $name | |
*/ | |
public function setName($name) | |
{ | |
$this->name = $name; | |
} | |
/** | |
* @param mixed $toppings | |
*/ | |
public function setToppings($toppings) | |
{ | |
$this->toppings = $toppings; | |
} | |
} | |
$reader = new JsonReader(); | |
$reader->json($json); | |
$map = [ | |
Donut::class => [ | |
'properties' => [ | |
'toppings' => Toppings::class, | |
'test' => Donut::class | |
] | |
] | |
]; | |
$mapper = new ObjectMapper($map); | |
$start = microtime(true); | |
$result = $mapper->map($json, Donut::class); | |
var_dump((microtime(true) - $start) * 1000); | |
$start = microtime(true); | |
$result = json_decode($json); | |
var_dump((microtime(true) - $start) * 1000); | |
$serializer = SerializerBuilder::create() | |
->addMetadataDir(__DIR__) | |
->setCacheDir(__DIR__) | |
->build(); | |
$start = microtime(true); | |
$object = $serializer->deserialize($json, Donut::class, 'json'); | |
var_dump((microtime(true) - $start) * 1000); | |
var_dump($result); | |
class ObjectMapper { | |
private $typeMap; | |
/** | |
* ObjectMapper constructor. | |
* @param $typeMap | |
*/ | |
public function __construct($typeMap) | |
{ | |
$this->typeMap = $typeMap; | |
} | |
public function map($data, $type) { | |
$reader = new JsonReader(); | |
$reader->json($data); | |
return $this->read($reader, $type); | |
} | |
private function read(JsonReader $reader, $type) { | |
$result = null; | |
while($reader->read()) { | |
switch ($reader->type()) { | |
case JsonReader::BOOL: | |
case JsonReader::NUMBER: | |
case JsonReader::STRING: | |
return $reader->value(); | |
case JsonReader::OBJECT: | |
$result = new $type; | |
return $this->readProperties($reader, $type, $result); | |
case JsonReader::END_OBJECT: | |
return $result; | |
case JsonReader::ARRAY: | |
return $this->readItems($reader, $type); | |
break; | |
case JsonReader::END_ARRAY: | |
return $result; | |
} | |
} | |
} | |
private function readProperties(JsonReader $reader, $type, $result) { | |
while ($reader->read()) { | |
switch ($reader->type()) { | |
case JsonReader::BOOL: | |
case JsonReader::NUMBER: | |
case JsonReader::STRING: | |
$method = 'set' . ucfirst($reader->name()); | |
$result->$method($reader->value()); | |
break; | |
case JsonReader::OBJECT: | |
$name = $reader->name(); | |
if (isset($this->typeMap[$type]['properties'][$name])) { | |
$propertyType = $this->typeMap[$type]['properties'][$name]; | |
} | |
$method = 'set' . ucfirst($reader->name()); | |
$object = new $propertyType; | |
$result->$method($this->readProperties($reader, $propertyType, $object)); | |
break; | |
case JsonReader::END_OBJECT: | |
return $result; | |
case JsonReader::ARRAY: | |
$name = $reader->name(); | |
if (isset($this->typeMap[$type]['properties'][$name])) { | |
$type = $this->typeMap[$type]['properties'][$name]; | |
} | |
$method = 'set' . ucfirst($reader->name()); | |
$items = $this->readItems($reader, $type); | |
$result->$method($items); | |
break; | |
case JsonReader::END_ARRAY: | |
break; | |
} | |
} | |
} | |
private function readItems(JsonReader $reader, $type) { | |
$result = []; | |
while ($reader->read()) { | |
switch ($reader->type()) { | |
case JsonReader::BOOL: | |
case JsonReader::NUMBER: | |
case JsonReader::STRING: | |
$result[] = $reader->value(); | |
break; | |
case JsonReader::OBJECT: | |
$object = new $type; | |
$result[] = $this->readProperties($reader, $type, $object); | |
break; | |
case JsonReader::END_OBJECT: | |
break; | |
case JsonReader::ARRAY: | |
$result[] = $this->read($reader, $type); | |
break; | |
case JsonReader::END_ARRAY: | |
return $result; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment