Skip to content

Commit d655317

Browse files
committed
wip example code
1 parent 6f5eea9 commit d655317

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

solution-attributes.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
#[Attribute(Attribute::TARGET_CLASS)]
4+
class Deserialize {}
5+
6+
#[Attribute(Attribute::TARGET_PROPERTY)]
7+
class Map {
8+
public function __construct(public string $mapFrom)
9+
{
10+
}
11+
}
12+
13+
#[Attribute(Attribute::TARGET_PROPERTY)]
14+
class Skip {
15+
16+
}
17+
18+
#[Deserialize]
19+
class CityBreak {
20+
public string $country;
21+
22+
#[Map('town')]
23+
public string $city;
24+
25+
public string $avgTemperature;
26+
27+
#[Skip()]
28+
public ?string $bestNeighbourhood = null;
29+
}
30+
31+
function camelCaseToSnakeCase(string $string): string
32+
{
33+
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
34+
}
35+
36+
function deserialize(string $data, string $className): object
37+
{
38+
$reflectionClass = new \ReflectionClass($className);
39+
$attrs = $reflectionClass->getAttributes(Deserialize::class);
40+
41+
if (empty($attrs)) {
42+
throw new \RuntimeException('Class cannot be deserialized');
43+
}
44+
45+
$attrs[0]->newInstance();
46+
47+
$object = new $className;
48+
49+
$data = json_decode($data, true);
50+
51+
foreach ($reflectionClass->getProperties() as $property) {
52+
if ($map = $property->getAttributes(Map::class)) {
53+
$key = $map[0]->newInstance()->mapFrom;
54+
55+
if (isset($data[$key])) {
56+
$object->{$property->getName()} = $data[$key];
57+
}
58+
59+
} elseif ($skip = $property->getAttributes(Skip::class)) {
60+
continue;
61+
} elseif (isset($data[camelCaseToSnakeCase($property->getName())])) {
62+
$object->{$property->getName()} = $data[camelCaseToSnakeCase($property->getName())];
63+
}
64+
}
65+
66+
return $object;
67+
}
68+
69+
$object = deserialize(
70+
json_encode([
71+
'country' => 'Austria',
72+
'town' => 'Vienna',
73+
'avg_temperature' => '13',
74+
'best_neighbourhood' => 'Penha de França'
75+
]),
76+
CityBreak::class
77+
);
78+
79+
var_dump($object);
80+

0 commit comments

Comments
 (0)