Completed
Pull Request — master (#925)
by Asmir
02:40
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 170
    public function __construct(
37
        int $options = JSON_PRESERVE_ZERO_FRACTION)
38
    {
39 170
        $this->dataStack = new \SplStack;
40 170
        $this->options = $options;
41 170
    }
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
     * @param SerializationContext $context
72
     * @return mixed
73
     */
74 75
    public function visitArray(array $data, array $type)
75
    {
76 75
        $this->dataStack->push($data);
77
78 75
        $rs = isset($type['params'][1]) ? new \ArrayObject() : array();
79
80 75
        $isList = isset($type['params'][0]) && !isset($type['params'][1]);
81
82 75
        $elType = $this->getElementType($type);
83 75
        foreach ($data as $k => $v) {
84
85
            try {
86 69
                $v = $this->navigator->accept($v, $elType);
87 6
            } catch (NotAcceptableException $e) {
88 6
                continue;
89
            }
90
91 66
            if ($isList) {
92 17
                $rs[] = $v;
93
            } else {
94 66
                $rs[$k] = $v;
95
            }
96
        }
97
98 75
        $this->dataStack->pop();
99 75
        return $rs;
100
    }
101
102 88
    public function startVisitingObject(ClassMetadata $metadata, object $data, array $type): void
103
    {
104 88
        $this->dataStack->push($this->data);
105 88
        $this->data = array();
106 88
    }
107
108 87
    public function endVisitingObject(ClassMetadata $metadata, object $data, array $type)
109
    {
110 87
        $rs = $this->data;
111 87
        $this->data = $this->dataStack->pop();
112
113
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
114 87
        if (empty($rs)) {
115 12
            $rs = new \ArrayObject();
116
        }
117
118 87
        return $rs;
119
    }
120
121 81
    public function visitProperty(PropertyMetadata $metadata, $v): void
122
    {
123
        try {
124 81
            $v = $this->navigator->accept($v, $metadata->type);
125 4
        } catch (NotAcceptableException $e) {
126 4
            return;
127
        }
128
129 81
        if (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) {
130 2
            return;
131
        }
132
133 80
        if ($metadata->inline) {
134 3
            if (\is_array($v) || ($v instanceof \ArrayObject)) {
135 3
                $this->data = array_merge($this->data, (array)$v);
136
            }
137
        } else {
138 79
            $this->data[$metadata->serializedName] = $v;
139
        }
140 80
    }
141
142
    /**
143
     * Checks if some data key exists.
144
     *
145
     * @param string $key
146
     * @return boolean
147
     */
148 1
    public function hasData($key)
149
    {
150 1
        return isset($this->data[$key]);
151
    }
152
153
    /**
154
     * Allows you to replace existing data on the current object/root element.
155
     *
156
     * @param string $key
157
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
158
     *                                                       It must not contain any objects anymore.
159
     */
160 2
    public function setData($key, $value)
161
    {
162 2
        $this->data[$key] = $value;
163 2
    }
164
165 140
    public function getResult($data)
166
    {
167 140
        $result = @json_encode($data, $this->options);
168
169 140
        switch (json_last_error()) {
170 140
            case JSON_ERROR_NONE:
171 138
                return $result;
172
173 2
            case JSON_ERROR_UTF8:
174 2
                throw new RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
175
176
            default:
177
                throw new RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
178
        }
179
    }
180
}
181