From b682e9ec0b75185b106af06367b4d09c3b1c4dd9 Mon Sep 17 00:00:00 2001 From: Hitalo Souza <63821277+enghitalo@users.noreply.github.com> Date: Mon, 12 Dec 2022 05:06:29 -0300 Subject: [PATCH] json2: decode time.Time, supporting unix timestamps (like `json`), as well as rfc3339 datetimes (#16653) --- vlib/x/json2/decode_struct_test.v | 13 ++++++++++- vlib/x/json2/encode_struct_test.v | 2 +- vlib/x/json2/json2.v | 37 ++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/vlib/x/json2/decode_struct_test.v b/vlib/x/json2/decode_struct_test.v index 3db6cdd697..b7777a08c7 100644 --- a/vlib/x/json2/decode_struct_test.v +++ b/vlib/x/json2/decode_struct_test.v @@ -8,7 +8,7 @@ const fixed_time = time.Time{ hour: 13 minute: 54 second: 25 - unix: 0 + unix: 1647006865 } type StringAlias = string @@ -77,4 +77,15 @@ fn test_types() { assert json.decode[StructType[int]]('{"val": "false"}')!.val == 0 assert json.decode[StructType[int]]('{"val": true}')!.val == 1 assert json.decode[StructType[int]]('{"val": false}')!.val == 0 + + assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val == fixed_time + assert json.decode[StructType[time.Time]]('{"val": "2022-03-11 13:54:25.000"}')!.val == fixed_time + assert json.decode[StructType[time.Time]]('{"val": 1647006865}')!.val == fixed_time + assert json.decode[StructType[time.Time]]('{"val": "1647006865"}')!.val == fixed_time + if x := json.decode[StructType[time.Time]]('{"val": "invalid time"}') { + assert false + } else { + // dump(err) + assert true + } } diff --git a/vlib/x/json2/encode_struct_test.v b/vlib/x/json2/encode_struct_test.v index d300b0dec9..4f67826668 100644 --- a/vlib/x/json2/encode_struct_test.v +++ b/vlib/x/json2/encode_struct_test.v @@ -8,7 +8,7 @@ const fixed_time = time.Time{ hour: 13 minute: 54 second: 25 - unix: 1647017665 + unix: 1647006865 } type StringAlias = string diff --git a/vlib/x/json2/json2.v b/vlib/x/json2/json2.v index 1ac3074637..5edf6986a1 100644 --- a/vlib/x/json2/json2.v +++ b/vlib/x/json2/json2.v @@ -50,7 +50,7 @@ pub fn decode[T](src string) !T { } $else $if field.typ is string { typ.$(field.name) = res[field.name]!.str() } $else $if field.typ is time.Time { - // typ.$(field.name) = res[field.name]!.str() + typ.$(field.name) = res[field.name]!.to_time()! } $else { return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose") } @@ -251,3 +251,38 @@ pub fn (f Any) as_map() map[string]Any { '0': f } } + +// to_time uses `Any` as a time.Time. +pub fn (f Any) to_time() !time.Time { + match f { + time.Time { + return f + } + i64 { + return time.unix(f) + } + string { + is_rfc3339 := f.len == 24 && f[23] == `Z` && f[10] == `T` + if is_rfc3339 { + return time.parse_rfc3339(f)! + } + mut is_unix_timestamp := true + for c in f { + if c == `-` || (c >= `0` && c <= `9`) { + continue + } + is_unix_timestamp = false + break + } + if is_unix_timestamp { + return time.unix(f.i64()) + } + // TODO - parse_iso8601 + // TODO - parse_rfc2822 + return time.parse(f)! + } + else { + return error('not a time value: ${f} of type: ${f.type_name()}') + } + } +}