v2 / vlib / x / json2 / json2.v
415 lines · 394 sloc · 7.08 KB · 3ffc951cf555dc4818309a507ccb9d0da4de748f
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module json2
5
6import time
7
8// i8 uses `Any` as a 16-bit integer.
9pub fn (f Any) i8() i8 {
10 match f {
11 i8 {
12 return f
13 }
14 i16, i32, int, i64, u8, u16, u32, u64, f32, f64, bool {
15 return i8(f)
16 }
17 string {
18 return f.i8()
19 }
20 else {
21 return 0
22 }
23 }
24}
25
26// i16 uses `Any` as a 16-bit integer.
27pub fn (f Any) i16() i16 {
28 match f {
29 i16 {
30 return f
31 }
32 i8, i32, int, i64, u8, u16, u32, u64, f32, f64, bool {
33 return i16(f)
34 }
35 string {
36 return f.i16()
37 }
38 else {
39 return 0
40 }
41 }
42}
43
44// int uses `Any` as an integer.
45pub fn (f Any) int() int {
46 match f {
47 int {
48 return f
49 }
50 i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, bool {
51 return int(f)
52 }
53 string {
54 return f.int()
55 }
56 else {
57 return 0
58 }
59 }
60}
61
62// i32 uses `Any` as a 32-bit integer.
63pub fn (f Any) i32() i32 {
64 match f {
65 i32 {
66 return f
67 }
68 i8, i16, int, i64, u8, u16, u32, u64, f32, f64, bool {
69 return i32(f)
70 }
71 string {
72 return f.i32()
73 }
74 else {
75 return 0
76 }
77 }
78}
79
80// i64 uses `Any` as a 64-bit integer.
81pub fn (f Any) i64() i64 {
82 match f {
83 i64 {
84 return f
85 }
86 i8, i16, i32, int, u8, u16, u32, u64, f32, f64, bool {
87 return i64(f)
88 }
89 string {
90 return f.i64()
91 }
92 else {
93 return 0
94 }
95 }
96}
97
98// u8 uses `Any` as a 8-bit unsigned integer.
99pub fn (f Any) u8() u8 {
100 match f {
101 u8 {
102 return f
103 }
104 u16, u32, u64, i8, i16, i32, int, i64, f32, f64, bool {
105 return u8(u16(f))
106 }
107 string {
108 return f.u8()
109 }
110 else {
111 return 0
112 }
113 }
114}
115
116// u16 uses `Any` as a 16-bit unsigned integer.
117pub fn (f Any) u16() u16 {
118 match f {
119 u16 {
120 return f
121 }
122 u8, u32, u64, i8, i16, i32, int, i64, f32, f64, bool {
123 return u16(f)
124 }
125 string {
126 return f.u16()
127 }
128 else {
129 return 0
130 }
131 }
132}
133
134// u32 uses `Any` as a 32-bit unsigned integer.
135pub fn (f Any) u32() u32 {
136 match f {
137 u32 {
138 return f
139 }
140 u8, u16, u64, i8, i16, i32, int, i64, f32, f64, bool {
141 return u32(f)
142 }
143 string {
144 return f.u32()
145 }
146 else {
147 return 0
148 }
149 }
150}
151
152// u64 uses `Any` as a 64-bit unsigned integer.
153pub fn (f Any) u64() u64 {
154 match f {
155 u64 {
156 return f
157 }
158 u8, u16, u32, i8, i16, i32, int, i64, f32, f64, bool {
159 return u64(f)
160 }
161 string {
162 return f.u64()
163 }
164 else {
165 return 0
166 }
167 }
168}
169
170// f32 uses `Any` as a 32-bit float.
171pub fn (f Any) f32() f32 {
172 match f {
173 f32 {
174 return f
175 }
176 bool, i8, i16, i32, int, i64, u8, u16, u32, u64, f64 {
177 return f32(f)
178 }
179 string {
180 return f.f32()
181 }
182 else {
183 return 0.0
184 }
185 }
186}
187
188// f64 uses `Any` as a 64-bit float.
189pub fn (f Any) f64() f64 {
190 match f {
191 f64 {
192 return f
193 }
194 i8, i16, i32, int, i64, u8, u16, u32, u64, f32 {
195 return f64(f)
196 }
197 string {
198 return f.f64()
199 }
200 else {
201 return 0.0
202 }
203 }
204}
205
206// bool uses `Any` as a bool.
207pub fn (f Any) bool() bool {
208 match f {
209 bool {
210 return f
211 }
212 string {
213 if f == 'false' {
214 return false
215 }
216 if f == 'true' {
217 return true
218 }
219 if f.len > 0 {
220 return f != '0' && f != '0.0'
221 } else {
222 return false
223 }
224 }
225 i8, i16, i32, int, i64 {
226 return i64(f) != 0
227 }
228 u8, u16, u32, u64 {
229 return u64(f) != 0
230 }
231 f32, f64 {
232 return f64(f) != 0.0
233 }
234 else {
235 return false
236 }
237 }
238}
239
240// arr uses `Any` as an array.
241@[deprecated: 'use as_array() instead']
242@[deprecated_after: '2026-03-27']
243pub fn (f Any) arr() []Any {
244 return f.as_array()
245}
246
247// as_array uses `Any` as an array.
248pub fn (f Any) as_array() []Any {
249 if f is []Any {
250 return f
251 } else if f is map[string]Any {
252 mut arr := []Any{}
253 for _, v in f {
254 arr << v
255 }
256 return arr
257 }
258 return [f]
259}
260
261// as_map uses `Any` as a map.
262pub fn (f Any) as_map() map[string]Any {
263 if f is map[string]Any {
264 return f
265 } else if f is []Any {
266 mut mp := map[string]Any{}
267 for i, fi in f {
268 mp['${i}'] = fi
269 }
270 return mp
271 }
272 return {
273 '0': f
274 }
275}
276
277pub fn (f Any) as_map_of_strings() map[string]string {
278 if f is map[string]Any {
279 mut ms := map[string]string{}
280 for k, v in f {
281 ms[k] = v.str()
282 }
283 return ms
284 }
285 if f is []Any {
286 mut ms := map[string]string{}
287 for i, fi in f {
288 ms['${i}'] = fi.str()
289 }
290 return ms
291 }
292 return {
293 '0': f.str()
294 }
295}
296
297// to_time uses `Any` as a time.Time.
298pub fn (f Any) to_time() !time.Time {
299 match f {
300 time.Time {
301 return f
302 }
303 i64 {
304 return time.unix(f)
305 }
306 string {
307 is_iso8601 := f[4] == `-` && f[7] == `-`
308 if is_iso8601 {
309 return time.parse_iso8601(f)!
310 }
311 is_rfc3339 := f.len == 24 && f[23] == `Z` && f[10] == `T`
312 if is_rfc3339 {
313 return time.parse_rfc3339(f)!
314 }
315 mut is_unix_timestamp := true
316 for c in f {
317 if c == `-` || (c >= `0` && c <= `9`) {
318 continue
319 }
320 is_unix_timestamp = false
321 break
322 }
323 if is_unix_timestamp {
324 return time.unix(f.i64())
325 }
326 // TODO: parse_iso8601
327 // TODO: parse_rfc2822
328 return time.parse(f)!
329 }
330 else {
331 return error('not a time value: ${f} of type: ${f.type_name()}')
332 }
333 }
334}
335
336// map_from converts a struct to a map of Any.
337pub fn map_from[T](t T) map[string]Any {
338 mut m := map[string]Any{}
339 $if T is $struct {
340 $for field in T.fields {
341 value := t.$(field.name)
342
343 $if field.is_array {
344 mut top_arr := unsafe { []Any{len: t.$(field.name).len} }
345 for idx, variable in value {
346 $if variable is $array {
347 top_arr[idx] = flatten_array(variable)
348 } $else {
349 top_arr[idx] = variable
350 }
351 }
352 m[field.name] = top_arr
353 top_arr.clear()
354 } $else $if field.is_struct {
355 m[field.name] = map_from(value)
356 } $else $if field.is_map {
357 // TODO
358 } $else $if field.is_alias {
359 // TODO
360 } $else $if field.is_option {
361 // TODO
362 } $else {
363 // TODO: simplify check of type & improve memory usage when convert
364 $if field.typ is string {
365 m[field.name] = value
366 } $else $if field.typ is bool {
367 m[field.name] = t.$(field.name)
368 } $else $if field.typ is i8 {
369 m[field.name] = t.$(field.name)
370 } $else $if field.typ is i16 {
371 m[field.name] = t.$(field.name)
372 } $else $if field.typ is i32 {
373 m[field.name] = t.$(field.name)
374 } $else $if field.typ is int {
375 m[field.name] = t.$(field.name)
376 } $else $if field.typ is i64 {
377 m[field.name] = t.$(field.name)
378 } $else $if field.typ is f32 {
379 m[field.name] = t.$(field.name)
380 } $else $if field.typ is f64 {
381 m[field.name] = t.$(field.name)
382 } $else $if field.typ is u8 {
383 m[field.name] = t.$(field.name)
384 } $else $if field.typ is u16 {
385 m[field.name] = t.$(field.name)
386 } $else $if field.typ is u32 {
387 m[field.name] = t.$(field.name)
388 } $else $if field.typ is u64 {
389 m[field.name] = t.$(field.name)
390 } $else {
391 // return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose")
392 }
393 }
394 }
395 }
396 return m
397}
398
399// flatten_array convert a array of values to array of Any
400@[inline]
401fn flatten_array[T](t []T) []Any {
402 $if t !is $array {
403 return Any(t)
404 } $else {
405 mut arr := []Any{}
406 for variable in t {
407 $if variable is $array {
408 arr << flatten_array(variable)
409 } $else {
410 arr << Any(variable)
411 }
412 }
413 return arr
414 }
415}
416