Passed
Push — master ( 87567e...de6cb3 )
by Asmir
25:58 queued 23:08
created

JsonSerializationVisitor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
namespace JMS\Serializer;
22
23
use JMS\Serializer\Exception\NotAcceptableException;
24
use JMS\Serializer\Exception\RuntimeException;
25
use JMS\Serializer\Metadata\ClassMetadata;
26
use JMS\Serializer\Metadata\PropertyMetadata;
27
use JMS\Serializer\Visitor\SerializationVisitorInterface;
28
29
final class JsonSerializationVisitor extends AbstractVisitor implements SerializationVisitorInterface
30
{
31
    private $options = JSON_PRESERVE_ZERO_FRACTION;
32
33
    private $dataStack;
34
    private $data;
35
36 171
    public function __construct(
37
        int $options = JSON_PRESERVE_ZERO_FRACTION)
38
    {
39 171
        $this->dataStack = new \SplStack;
40 171
        $this->options = $options;
41 171
    }
42
43 14
    public function visitNull($data, array $type)
44
    {
45 14
        return null;
46
    }
47
48 94
    public function visitString(string $data, array $type)
49
    {
50 94
        return $data;
51
    }
52
53 9
    public function visitBoolean(bool $data, array $type)
54
    {
55 9
        return $data;
56
    }
57
58 25
    public function visitInteger(int $data, array $type)
59
    {
60 25
        return $data;
61
    }
62
63 12
    public function visitDouble(float $data, array $type)
64
    {
65 12
        return $data;
66
    }
67
68
    /**
69
     * @param array $data
70
     * @param array $type
71
     * @return mixed
72
     */
73 75
    public function visitArray(array $data, array $type)
74
    {
75 75
        $this->dataStack->push($data);
76
77 75
        $rs = isset($type['params'][1]) ? new \ArrayObject() : [];
78
79 75
        $isList = isset($type['params'][0]) && !isset($type['params'][1]);
80
81 75
        $elType = $this->getElementType($type);
82 75
        foreach ($data as $k => $v) {
83
84
            try {
85 69
                $v = $this->navigator->accept($v, $elType);
86 6
            } catch (NotAcceptableException $e) {
87 6
                continue;
88
            }
89
90 66
            if ($isList) {
91 17
                $rs[] = $v;
92
            } else {
93 66
                $rs[$k] = $v;
94
            }
95
        }
96
97 75
        $this->dataStack->pop();
98 75
        return $rs;
99
    }
100
101 88
    public function startVisitingObject(ClassMetadata $metadata, object $data, array $type): void
102
    {
103 88
        $this->dataStack->push($this->data);
104 88
        $this->data = [];
105 88
    }
106
107 87
    public function endVisitingObject(ClassMetadata $metadata, object $data, array $type)
108
    {
109 87
        $rs = $this->data;
110 87
        $this->data = $this->dataStack->pop();
111
112
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
113 87
        if (empty($rs)) {
114 12
            $rs = new \ArrayObject();
115
        }
116
117 87
        return $rs;
118
    }
119
120 81
    public function visitProperty(PropertyMetadata $metadata, $v): void
121
    {
122
        try {
123 81
            $v = $this->navigator->accept($v, $metadata->type);
124 4
        } catch (NotAcceptableException $e) {
125 4
            return;
126
        }
127
128 81
        if (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) {
129 2
            return;
130
        }
131
132 80
        if ($metadata->inline) {
133 3
            if (\is_array($v) || ($v instanceof \ArrayObject)) {
134 3
                $this->data = array_merge($this->data, (array)$v);
135
            }
136
        } else {
137 79
            $this->data[$metadata->serializedName] = $v;
138
        }
139 80
    }
140
141
    /**
142
     * Checks if some data key exists.
143
     *
144
     * @param string $key
145
     * @return boolean
146
     */
147 1
    public function hasData(string $key): bool
148
    {
149 1
        return isset($this->data[$key]);
150
    }
151
152
    /**
153
     * Allows you to replace existing data on the current object/root element.
154
     *
155
     * @param string $key
156
     * @param mixed $value This value must either be a regular scalar, or an array.
157
     *                                                       It must not contain any objects anymore.
158
     */
159 2
    public function setData(string $key, $value): void
160
    {
161 2
        $this->data[$key] = $value;
162 2
    }
163
164 141
    public function getResult($data)
165
    {
166 141
        $result = @json_encode($data, $this->options);
167
168 141
        switch (json_last_error()) {
169 141
            case JSON_ERROR_NONE:
170 139
                return $result;
171
172 2
            case JSON_ERROR_UTF8:
173 2
                throw new RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
174
175
            default:
176
                throw new RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
177
        }
178
    }
179
}
180