1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace JMS\Serializer; |
||||
6 | |||||
7 | use JMS\Serializer\Exception\NotAcceptableException; |
||||
8 | use JMS\Serializer\Exception\RuntimeException; |
||||
9 | use JMS\Serializer\Metadata\ClassMetadata; |
||||
10 | use JMS\Serializer\Metadata\PropertyMetadata; |
||||
11 | use JMS\Serializer\Visitor\SerializationVisitorInterface; |
||||
12 | |||||
13 | final class JsonSerializationVisitor extends AbstractVisitor implements SerializationVisitorInterface |
||||
14 | { |
||||
15 | /** |
||||
16 | * @var int |
||||
17 | */ |
||||
18 | private $options; |
||||
19 | |||||
20 | /** |
||||
21 | * @var array |
||||
22 | */ |
||||
23 | 180 | private $dataStack; |
|||
24 | /** |
||||
25 | * @var \ArrayObject|array |
||||
26 | 180 | */ |
|||
27 | 180 | private $data; |
|||
28 | 180 | ||||
29 | public function __construct( |
||||
30 | 14 | int $options = JSON_PRESERVE_ZERO_FRACTION |
|||
31 | ) { |
||||
32 | 14 | $this->dataStack = []; |
|||
33 | $this->options = $options; |
||||
34 | } |
||||
35 | 97 | ||||
36 | /** |
||||
37 | 97 | * {@inheritdoc} |
|||
38 | */ |
||||
39 | public function visitNull($data, array $type) |
||||
40 | 9 | { |
|||
41 | return null; |
||||
42 | 9 | } |
|||
43 | |||||
44 | /** |
||||
45 | 30 | * {@inheritdoc} |
|||
46 | */ |
||||
47 | 30 | public function visitString(string $data, array $type) |
|||
48 | { |
||||
49 | return $data; |
||||
50 | 12 | } |
|||
51 | |||||
52 | 12 | /** |
|||
53 | * {@inheritdoc} |
||||
54 | */ |
||||
55 | public function visitBoolean(bool $data, array $type) |
||||
56 | { |
||||
57 | return $data; |
||||
58 | } |
||||
59 | |||||
60 | 81 | /** |
|||
61 | * {@inheritdoc} |
||||
62 | 81 | */ |
|||
63 | public function visitInteger(int $data, array $type) |
||||
64 | 81 | { |
|||
65 | return $data; |
||||
66 | 81 | } |
|||
67 | |||||
68 | 81 | /** |
|||
69 | 81 | * {@inheritdoc} |
|||
70 | */ |
||||
71 | public function visitDouble(float $data, array $type) |
||||
72 | 73 | { |
|||
73 | 6 | $precision = $type['params'][0] ?? null; |
|||
74 | 6 | if (!is_int($precision)) { |
|||
75 | return $data; |
||||
76 | } |
||||
77 | 70 | ||||
78 | 19 | $roundMode = $type['params'][1] ?? null; |
|||
79 | $roundMode = $this->mapRoundMode($roundMode); |
||||
80 | 70 | ||||
81 | return round($data, $precision, $roundMode); |
||||
82 | } |
||||
83 | |||||
84 | 81 | public function visitArray(array $data, array $type) |
|||
85 | 81 | { |
|||
86 | \array_push($this->dataStack, $data); |
||||
87 | |||||
88 | 97 | $rs = isset($type['params'][1]) ? new \ArrayObject() : []; |
|||
89 | |||||
90 | 97 | $isList = isset($type['params'][0]) && !isset($type['params'][1]); |
|||
91 | 97 | ||||
92 | 97 | $elType = $this->getElementType($type); |
|||
93 | foreach ($data as $k => $v) { |
||||
94 | 96 | try { |
|||
95 | $v = $this->navigator->accept($v, $elType); |
||||
0 ignored issues
–
show
|
|||||
96 | 96 | } catch (NotAcceptableException $e) { |
|||
97 | 96 | continue; |
|||
98 | } |
||||
99 | 96 | ||||
100 | 12 | if ($isList) { |
|||
101 | $rs[] = $v; |
||||
102 | 89 | } else { |
|||
103 | $rs[$k] = $v; |
||||
104 | } |
||||
105 | 90 | } |
|||
106 | |||||
107 | \array_pop($this->dataStack); |
||||
108 | 90 | ||||
109 | 4 | return $rs; |
|||
110 | 4 | } |
|||
111 | |||||
112 | public function startVisitingObject(ClassMetadata $metadata, object $data, array $type): void |
||||
113 | 90 | { |
|||
114 | 2 | \array_push($this->dataStack, $this->data); |
|||
115 | $this->data = true === $metadata->isMap ? new \ArrayObject() : []; |
||||
116 | } |
||||
117 | 89 | ||||
118 | 9 | /** |
|||
119 | * @return array|\ArrayObject |
||||
120 | */ |
||||
121 | 9 | public function endVisitingObject(ClassMetadata $metadata, object $data, array $type) |
|||
122 | 9 | { |
|||
123 | $rs = $this->data; |
||||
124 | $this->data = \array_pop($this->dataStack); |
||||
125 | |||||
126 | 82 | if (true !== $metadata->isList && empty($rs)) { |
|||
127 | return new \ArrayObject(); |
||||
128 | 89 | } |
|||
129 | |||||
130 | return $rs; |
||||
131 | } |
||||
132 | |||||
133 | /** |
||||
134 | * {@inheritdoc} |
||||
135 | */ |
||||
136 | public function visitProperty(PropertyMetadata $metadata, $v): void |
||||
137 | 1 | { |
|||
138 | try { |
||||
139 | 1 | $v = $this->navigator->accept($v, $metadata->type); |
|||
0 ignored issues
–
show
It seems like
$metadata->type can also be of type JMS\Serializer\Metadata\TypeArray ; however, parameter $type of JMS\Serializer\GraphNavigatorInterface::accept() does only seem to accept array|null , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
140 | } catch (NotAcceptableException $e) { |
||||
141 | return; |
||||
142 | } |
||||
143 | |||||
144 | if (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) { |
||||
145 | return; |
||||
146 | } |
||||
147 | |||||
148 | if ($metadata->inline) { |
||||
149 | if (\is_array($v) || ($v instanceof \ArrayObject)) { |
||||
150 | // concatenate the two array-like structures |
||||
151 | 2 | // is there anything faster? |
|||
152 | foreach ($v as $key => $value) { |
||||
153 | 2 | $this->data[$key] = $value; |
|||
154 | 2 | } |
|||
155 | } |
||||
156 | 150 | } else { |
|||
157 | $this->data[$metadata->serializedName] = $v; |
||||
158 | 150 | } |
|||
159 | } |
||||
160 | 150 | ||||
161 | 150 | /** |
|||
162 | 148 | * Checks if some data key exists. |
|||
163 | */ |
||||
164 | 2 | public function hasData(string $key): bool |
|||
165 | 2 | { |
|||
166 | return isset($this->data[$key]); |
||||
167 | } |
||||
168 | |||||
169 | /** |
||||
170 | * @deprecated Use `::visitProperty(new StaticPropertyMetadata('', 'name', 'value'), 'value')` instead |
||||
171 | * |
||||
172 | * Allows you to replace existing data on the current object element. |
||||
173 | * |
||||
174 | * @param mixed $value This value must either be a regular scalar, or an array. |
||||
175 | * It must not contain any objects anymore. |
||||
176 | */ |
||||
177 | public function setData(string $key, $value): void |
||||
178 | { |
||||
179 | $this->data[$key] = $value; |
||||
180 | } |
||||
181 | |||||
182 | /** |
||||
183 | * {@inheritdoc} |
||||
184 | */ |
||||
185 | public function getResult($data) |
||||
186 | { |
||||
187 | $this->navigator = null; |
||||
188 | |||||
189 | $result = @json_encode($data, $this->options); |
||||
190 | |||||
191 | switch (json_last_error()) { |
||||
192 | case JSON_ERROR_NONE: |
||||
193 | return $result; |
||||
194 | |||||
195 | case JSON_ERROR_UTF8: |
||||
196 | throw new RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.'); |
||||
197 | |||||
198 | default: |
||||
199 | throw new RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error())); |
||||
200 | } |
||||
201 | } |
||||
202 | } |
||||
203 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.