6
6
7
7
class AvscToJson implements ConverterInterface
8
8
{
9
+ /** @var array<string,mixed> $options */
9
10
private array $ options ;
10
11
12
+ /**
13
+ * @param string $avscSchema
14
+ * @param array<string,mixed> $options
15
+ * @return string
16
+ */
11
17
public function convert (string $ avscSchema , array $ options ): string
12
18
{
13
19
$ this ->options = $ options ;
14
- $ avscArray = json_decode ($ avscSchema , true );
20
+
21
+ /** @var mixed[] $avscArray */
22
+ $ avscArray = json_decode ($ avscSchema , true , JSON_THROW_ON_ERROR );
15
23
$ jsonArray = $ this ->convertAvro ($ avscArray );
24
+
25
+ /** @var string $rawJson */
16
26
$ rawJson = json_encode ($ jsonArray );
17
27
$ json = $ this ->fixAvroTypes ($ rawJson );
18
28
19
29
return $ json ;
20
30
}
21
31
32
+ /**
33
+ * @param mixed[] $avscArray
34
+ * @return mixed[]
35
+ */
22
36
private function convertAvro (array $ avscArray ): array
23
37
{
24
38
$ jsonArray = [];
@@ -30,21 +44,28 @@ private function convertAvro(array $avscArray): array
30
44
if ('type ' === $ key && 'array ' === $ value ) {
31
45
$ jsonArray [$ key ] = $ value ;
32
46
47
+ /** @var string|mixed[] $items */
48
+ $ items = $ avscArray ['items ' ];
49
+
33
50
if (
34
- true === $ this ->isBasicType ($ avscArray ['items ' ])
35
- || (true === is_array ($ avscArray ['items ' ]) && true === $ this ->isBasicTypeArray ($ avscArray ['items ' ]))
51
+ true === $ this ->isBasicType ($ items )
52
+ || (true === is_array ($ items ) && true === $ this ->isBasicTypeArray ($ items ))
53
+ ) {
54
+ $ jsonArray ['items ' ] = $ items ;
55
+ } elseif (
56
+ true === is_array ($ items )
57
+ && true === isset ($ items ['type ' ])
58
+ && 'record ' === $ items ['type ' ]
36
59
) {
37
- $ jsonArray ['items ' ] = $ avscArray ['items ' ];
38
- } elseif (true === isset ($ avscArray ['items ' ]['type ' ]) && 'record ' === $ avscArray ['items ' ]['type ' ]) {
39
- $ jsonArray ['items ' ] = $ this ->convertAvro ($ avscArray ['items ' ]);
40
- } else {
41
- $ jsonArray ['items ' ] = $ this ->getAnyOf ($ avscArray ['items ' ]);
60
+ $ jsonArray ['items ' ] = $ this ->convertAvro ($ items );
61
+ } elseif (true === is_array ($ items )) {
62
+ $ jsonArray ['items ' ] = $ this ->getAnyOf ($ items );
42
63
}
43
64
}
44
- if ('name ' === $ key ) {
65
+ if ('name ' === $ key && true === is_string ( $ value ) ) {
45
66
$ jsonArray ['title ' ] = $ this ->snakeToPascal ($ value );
46
67
}
47
- if ('fields ' === $ key ) {
68
+ if ('fields ' === $ key && true === is_array ( $ value ) ) {
48
69
$ jsonArray ['properties ' ] = $ this ->convertAvroFieldsToJsonFields ($ value );
49
70
$ requiredFields = $ this ->getRequiredFields ($ value );
50
71
@@ -57,11 +78,16 @@ private function convertAvro(array $avscArray): array
57
78
return $ jsonArray ;
58
79
}
59
80
81
+ /**
82
+ * @param mixed[] $avroFields
83
+ * @return mixed[]
84
+ */
60
85
private function convertAvroFieldsToJsonFields (array $ avroFields ): array
61
86
{
62
87
$ fields = [];
63
88
64
89
foreach ($ avroFields as $ field ) {
90
+ /** @var string|mixed[] $fieldType */
65
91
$ fieldType = $ field ['type ' ];
66
92
67
93
if (
@@ -80,13 +106,19 @@ private function convertAvroFieldsToJsonFields(array $avroFields): array
80
106
return $ fields ;
81
107
}
82
108
109
+ /**
110
+ * @param mixed[] $avroFields
111
+ * @return mixed[]
112
+ */
83
113
private function getRequiredFields (array $ avroFields ): array
84
114
{
85
115
$ requiredFields = [];
86
116
87
117
foreach ($ avroFields as $ field ) {
88
118
if (
89
- true === $ this ->options ['markNoDefaultAsRequired ' ] && false === array_key_exists ('default ' , $ field )
119
+ true === $ this ->options ['markNoDefaultAsRequired ' ]
120
+ && true === is_array ($ field )
121
+ && false === array_key_exists ('default ' , $ field )
90
122
) {
91
123
$ requiredFields [] = $ field ['name ' ];
92
124
} elseif (false === $ this ->options ['markNoDefaultAsRequired ' ]) {
@@ -97,17 +129,28 @@ private function getRequiredFields(array $avroFields): array
97
129
return $ requiredFields ;
98
130
}
99
131
132
+ /**
133
+ * @param mixed[] $types
134
+ * @return mixed[]
135
+ */
100
136
private function getAnyOf (array $ types )
101
137
{
102
138
$ anyOf = [];
103
139
104
140
foreach ($ types as $ type ) {
141
+ if (false === is_string ($ type ) && false === is_array ($ type )) {
142
+ continue ;
143
+ }
105
144
$ anyOf ['anyOf ' ][] = $ this ->getAnyOfType ($ type );
106
145
}
107
146
108
147
return $ anyOf ;
109
148
}
110
149
150
+ /**
151
+ * @param string|mixed[] $type
152
+ * @return mixed[]|string[]
153
+ */
111
154
private function getAnyOfType ($ type )
112
155
{
113
156
if (true === is_string ($ type )) {
@@ -117,9 +160,16 @@ private function getAnyOfType($type)
117
160
}
118
161
}
119
162
163
+ /**
164
+ * @param mixed[] $fieldTypes
165
+ * @return bool
166
+ */
120
167
private function isBasicTypeArray (array $ fieldTypes ): bool
121
168
{
122
169
foreach ($ fieldTypes as $ type ) {
170
+ if (false === is_string ($ type ) && false === is_array ($ type )) {
171
+ continue ;
172
+ }
123
173
if (false === $ this ->isBasicType ($ type )) {
124
174
return false ;
125
175
}
@@ -128,6 +178,10 @@ private function isBasicTypeArray(array $fieldTypes): bool
128
178
return true ;
129
179
}
130
180
181
+ /**
182
+ * @param string|mixed[] $type
183
+ * @return bool
184
+ */
131
185
private function isBasicType ($ type )
132
186
{
133
187
if (false === is_string ($ type )) {
@@ -142,13 +196,14 @@ private function snakeToPascal(string $input): string
142
196
return str_replace (' ' , '' , ucwords (str_replace ('_ ' , ' ' , $ input )));
143
197
}
144
198
145
- private function fixAvroTypes (string $ rawJson )
199
+ private function fixAvroTypes (string $ rawJson ): string
146
200
{
147
201
$ json = str_replace ('int ' , 'integer ' , $ rawJson );
148
202
$ json = str_replace ('long ' , 'number ' , $ json );
149
203
$ json = str_replace ('float ' , 'number ' , $ json );
150
204
$ json = str_replace ('double ' , 'number ' , $ json );
151
205
$ json = str_replace ('bytes ' , 'string ' , $ json );
206
+
152
207
return $ json ;
153
208
}
154
209
}
0 commit comments