Completed
Push — master ( 0d7a9a...ac7eed )
by Asmir
07:43
created

JsonSerializationVisitor::visitString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 3
crap 2
1
<?php
2
3
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer;
20
21
use JMS\Serializer\Metadata\ClassMetadata;
22
use JMS\Serializer\Exception\InvalidArgumentException;
23
use JMS\Serializer\Metadata\PropertyMetadata;
24
25
class JsonSerializationVisitor extends GenericSerializationVisitor
0 ignored issues
show
Deprecated Code introduced by
The class JMS\Serializer\GenericSerializationVisitor has been deprecated.

This class, trait or interface has been deprecated.

Loading history...
26
{
27
    private $options = 0;
28
29
    private $navigator;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
30
    private $root;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
31
    private $dataStack;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
32
    private $data;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
33
34 144
    public function setNavigator(GraphNavigator $navigator)
35
    {
36 144
        $this->navigator = $navigator;
37 144
        $this->root = null;
38 144
        $this->dataStack = new \SplStack;
39 144
    }
40
41
    /**
42
     * @return GraphNavigator
43
     */
44
    public function getNavigator()
45
    {
46
        return $this->navigator;
47
    }
48
49 28
    public function visitNull($data, array $type, Context $context)
50
    {
51 28
        return null;
52
    }
53
54 88
    public function visitString($data, array $type, Context $context)
55
    {
56 88
        if (null === $this->root) {
57 9
            $this->root = $data;
58 9
        }
59
60 88
        return (string) $data;
61
    }
62
63 9
    public function visitBoolean($data, array $type, Context $context)
64
    {
65 9
        if (null === $this->root) {
66 5
            $this->root = $data;
67 5
        }
68
69 9
        return (boolean) $data;
70
    }
71
72 26
    public function visitInteger($data, array $type, Context $context)
73
    {
74 26
        if (null === $this->root) {
75 4
            $this->root = $data;
76 4
        }
77
78 26
        return (int) $data;
79
    }
80
81 13
    public function visitDouble($data, array $type, Context $context)
82
    {
83 13
        if (null === $this->root) {
84 7
            $this->root = $data;
85 7
        }
86
87 13
        return (float) $data;
88
    }
89
90
    /**
91
     * @param array $data
92
     * @param array $type
93
     * @param Context $context
94
     * @return mixed
95
     */
96 70
    public function visitArray($data, array $type, Context $context)
97
    {
98 70
        $this->dataStack->push($data);
99
100 70
        $isHash = isset($type['params'][1]);
101
102 70
        if (null === $this->root) {
103 49
            $this->root = $isHash ? new \ArrayObject() : array();
104 49
            $rs = &$this->root;
105 49
        } else {
106 23
            $rs = $isHash ? new \ArrayObject() : array();
107
        }
108
109 70
        $isList = isset($type['params'][0]) && ! isset($type['params'][1]);
110
111 70
        foreach ($data as $k => $v) {
112 64
            $v = $this->navigator->accept($v, $this->getElementType($type), $context);
113
114 64
            if (null === $v && $context->shouldSerializeNull() !== true) {
115 3
                continue;
116
            }
117
118 64
            if ($isList) {
119 17
                $rs[] = $v;
120 17
            } else {
121 51
                $rs[$k] = $v;
122
            }
123 70
        }
124
125 70
        $this->dataStack->pop();
126 70
        return $rs;
127
    }
128
129 81
    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
130
    {
131 81
        if (null === $this->root) {
132 66
            $this->root = new \stdClass;
133 66
        }
134
135 81
        $this->dataStack->push($this->data);
136 81
        $this->data = array();
137 81
    }
138
139 80
    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
140
    {
141 80
        $rs = $this->data;
142 80
        $this->data = $this->dataStack->pop();
143
144
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
145 80
        if (empty($rs)) {
146 11
            $rs = new \ArrayObject();
0 ignored issues
show
Bug Compatibility introduced by
The expression new \ArrayObject(); of type ArrayObject adds the type ArrayObject to the return on line 153 which is incompatible with the return type of the parent method JMS\Serializer\GenericSe...itor::endVisitingObject of type array.
Loading history...
147 11
        }
148
149 80
        if ($this->root instanceof \stdClass && 0 === $this->dataStack->count()) {
150 65
            $this->root = $rs;
151 65
        }
152
153 80
        return $rs;
154
    }
155
156 77
    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
157
    {
158 77
        $v = $this->accessor->getValue($data, $metadata);
159
160 76
        $v = $this->navigator->accept($v, $metadata->type, $context);
161 76
        if ((null === $v && $context->shouldSerializeNull() !== true)
162 74
            || (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || is_array($v)) && 0 === count($v))
163 76
        ) {
164 16
            return;
165
        }
166
167 73
        $k = $this->namingStrategy->translateName($metadata);
168
169 73
        if ($metadata->inline) {
170 2
            if (is_array($v)) {
171 1
                $this->data = array_merge($this->data, $v);
172 1
            }
173 2
        } else {
174 73
            $this->data[$k] = $v;
175
        }
176 73
    }
177
178
    /**
179
     * Allows you to add additional data to the current object/root element.
180
     * @deprecated use setData instead
181
     * @param string $key
182
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
183
     *                                                       It must not contain any objects anymore.
184
     */
185 1
    public function addData($key, $value)
186
    {
187 1
        if (isset($this->data[$key])) {
188
            throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key));
189
        }
190
191 1
        $this->data[$key] = $value;
192 1
    }
193
194
    /**
195
     * Checks if some data key exists.
196
     *
197
     * @param string $key
198
     * @return boolean
199
     */
200 1
    public function hasData($key)
201
    {
202 1
        return isset($this->data[$key]);
203
    }
204
205
    /**
206
     * Allows you to replace existing data on the current object/root element.
207
     *
208
     * @param string $key
209
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
210
     *                                                       It must not contain any objects anymore.
211
     */
212 1
    public function setData($key, $value)
213
    {
214 1
        $this->data[$key] = $value;
215 1
    }
216
217 144
    public function getRoot()
218
    {
219 144
        return $this->root;
220
    }
221
222
    /**
223
     * @param array|\ArrayObject $data the passed data must be understood by whatever encoding function is applied later.
224
     */
225 7
    public function setRoot($data)
226
    {
227 7
        $this->root = $data;
228 7
    }
229
230
231 133
    public function getResult()
232
    {
233 133
        $result = @json_encode($this->getRoot(), $this->options);
234
235 133
        switch (json_last_error()) {
236 133
            case JSON_ERROR_NONE:
237 131
                return $result;
238
239 2
            case JSON_ERROR_UTF8:
240 2
                throw new \RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
241
242
            default:
243
                throw new \RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
244
        }
245
    }
246
247
    public function getOptions()
248
    {
249
        return $this->options;
250
    }
251
252
    public function setOptions($options)
253
    {
254
        $this->options = (integer) $options;
255
    }
256
}
257