Completed
Pull Request — master (#923)
by Asmir
04:23 queued 01:58
created

JsonSerializationVisitor::setData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Accessor\AccessorStrategyInterface;
24
use JMS\Serializer\Exception\NotAcceptableException;
25
use JMS\Serializer\Exception\RuntimeException;
26
use JMS\Serializer\Metadata\ClassMetadata;
27
use JMS\Serializer\Metadata\PropertyMetadata;
28
29
class JsonSerializationVisitor extends AbstractVisitor implements SerializationVisitorInterface
30
{
31
    private $options = JSON_PRESERVE_ZERO_FRACTION;
32
33
    private $dataStack;
34
    private $data;
35
36
37 170
    public function __construct(
38
        GraphNavigatorInterface $navigator,
39
        SerializationContext $context,
40
        int $options = JSON_PRESERVE_ZERO_FRACTION)
41
    {
42 170
        parent::__construct($navigator, $context);
43 170
        $this->dataStack = new \SplStack;
44 170
        $this->options = $options;
45 170
    }
46
47 14
    public function visitNull($data, array $type)
48
    {
49 14
        return null;
50
    }
51
52 94
    public function visitString(string $data, array $type)
53
    {
54 94
        return $data;
55
    }
56
57 9
    public function visitBoolean(bool $data, array $type)
58
    {
59 9
        return $data;
60
    }
61
62 25
    public function visitInteger(int $data, array $type)
63
    {
64 25
        return $data;
65
    }
66
67 12
    public function visitDouble(float $data, array $type)
68
    {
69 12
        return $data;
70
    }
71
72
    /**
73
     * @param array $data
74
     * @param array $type
75
     * @param SerializationContext $context
76
     * @return mixed
77
     */
78 75
    public function visitArray(array $data, array $type)
79
    {
80 75
        $this->dataStack->push($data);
81
82 75
        $rs = isset($type['params'][1]) ? new \ArrayObject() : array();
83
84 75
        $isList = isset($type['params'][0]) && !isset($type['params'][1]);
85
86 75
        $elType = $this->getElementType($type);
87 75
        foreach ($data as $k => $v) {
88
89
            try {
90 69
                $v = $this->navigator->accept($v, $elType, $this->context);
91 6
            } catch (NotAcceptableException $e) {
92 6
                continue;
93
            }
94
95 66
            if ($isList) {
96 17
                $rs[] = $v;
97
            } else {
98 66
                $rs[$k] = $v;
99
            }
100
        }
101
102 75
        $this->dataStack->pop();
103 75
        return $rs;
104
    }
105
106 88
    public function startVisitingObject(ClassMetadata $metadata, object $data, array $type): void
107
    {
108 88
        $this->dataStack->push($this->data);
109 88
        $this->data = array();
110 88
    }
111
112 87
    public function endVisitingObject(ClassMetadata $metadata, object $data, array $type)
113
    {
114 87
        $rs = $this->data;
115 87
        $this->data = $this->dataStack->pop();
116
117
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
118 87
        if (empty($rs)) {
119 12
            $rs = new \ArrayObject();
120
        }
121
122 87
        return $rs;
123
    }
124
125 81
    public function visitProperty(PropertyMetadata $metadata, $v): void
126
    {
127
        try {
128 81
            $v = $this->navigator->accept($v, $metadata->type, $this->context);
129 4
        } catch (NotAcceptableException $e) {
130 4
            return;
131
        }
132
133 81
        if (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) {
134 2
            return;
135
        }
136
137 80
        if ($metadata->inline) {
138 3
            if (\is_array($v) || ($v instanceof \ArrayObject)) {
139 3
                $this->data = array_merge($this->data, (array)$v);
140
            }
141
        } else {
142 79
            $this->data[$metadata->serializedName] = $v;
143
        }
144 80
    }
145
146
    /**
147
     * Checks if some data key exists.
148
     *
149
     * @param string $key
150
     * @return boolean
151
     */
152 1
    public function hasData($key)
153
    {
154 1
        return isset($this->data[$key]);
155
    }
156
157
    /**
158
     * Allows you to replace existing data on the current object/root element.
159
     *
160
     * @param string $key
161
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
162
     *                                                       It must not contain any objects anymore.
163
     */
164 2
    public function setData($key, $value)
165
    {
166 2
        $this->data[$key] = $value;
167 2
    }
168
169 140
    public function getResult($data)
170
    {
171 140
        $result = @json_encode($data, $this->options);
172
173 140
        switch (json_last_error()) {
174 140
            case JSON_ERROR_NONE:
175 138
                return $result;
176
177 2
            case JSON_ERROR_UTF8:
178 2
                throw new RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
179
180
            default:
181
                throw new RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
182
        }
183
    }
184
}
185