JsonSerializationVisitor::visitInteger()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
Bug introduced by
The method accept() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
                /** @scrutinizer ignore-call */ 
96
                $v = $this->navigator->accept($v, $elType);

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.

Loading history...
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
Bug introduced by
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 ignore-type  annotation

139
            $v = $this->navigator->accept($v, /** @scrutinizer ignore-type */ $metadata->type);
Loading history...
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