Skip to content

Commit d249bfb

Browse files
authored
decoder2: fix remaining json2 discrepancies (#25029)
1 parent 195f161 commit d249bfb

5 files changed

Lines changed: 158 additions & 64 deletions

File tree

vlib/time/json_decode.c.v

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
11
module time
22

3-
// from_json_string implements a custom decoder for json2
3+
// from_json_string implements a custom decoder for json2 (unix)
4+
pub fn (mut t Time) from_json_number(raw_number string) ! {
5+
t = unix(raw_number.i64())
6+
}
7+
8+
// from_json_string implements a custom decoder for json2 (iso8601/rfc3339/unix)
49
pub fn (mut t Time) from_json_string(raw_string string) ! {
5-
t = parse_rfc3339(raw_string) or { Time{} }
10+
is_iso8601 := raw_string[4] == `-` && raw_string[7] == `-`
11+
if is_iso8601 {
12+
t = parse_iso8601(raw_string)!
13+
return
14+
}
15+
16+
is_rfc3339 := raw_string.len == 24 && raw_string[23] == `Z` && raw_string[10] == `T`
17+
if is_rfc3339 {
18+
t = parse_rfc3339(raw_string)!
19+
return
20+
}
21+
22+
mut is_unix_timestamp := true
23+
for c in raw_string {
24+
if c == `-` || (c >= `0` && c <= `9`) {
25+
continue
26+
}
27+
is_unix_timestamp = false
28+
break
29+
}
30+
if is_unix_timestamp {
31+
t = unix(raw_string.i64())
32+
return
33+
}
34+
35+
return error('Expected iso8601/rfc3339/unix time but got: ${raw_string}')
636
}

vlib/x/json2/decoder2/decode.v

Lines changed: 110 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ fn (mut checker Decoder) check_json_format(val string) ! {
306306

307307
// skip whitespace
308308
for val[checker.checker_idx] in whitespace_chars {
309-
if checker.checker_idx >= checker_end - 1 {
309+
if checker.checker_idx == checker_end {
310310
break
311311
}
312312
checker.checker_idx++
@@ -349,7 +349,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
349349
for val[checker.checker_idx] != `}` {
350350
// skip whitespace
351351
for val[checker.checker_idx] in whitespace_chars {
352-
if checker.checker_idx >= checker_end - 1 {
352+
if checker.checker_idx == checker_end {
353+
checker.checker_idx--
353354
break
354355
}
355356
checker.checker_idx++
@@ -367,7 +368,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
367368
checker.check_json_format(val)!
368369

369370
for val[checker.checker_idx] != `:` {
370-
if checker.checker_idx >= checker_end - 1 {
371+
if checker.checker_idx == checker_end {
372+
checker.checker_idx--
371373
return checker.checker_error('EOF error: key colon not found')
372374
}
373375
if val[checker.checker_idx] !in whitespace_chars {
@@ -390,19 +392,33 @@ fn (mut checker Decoder) check_json_format(val string) ! {
390392
match val[checker.checker_idx] {
391393
`"`, `[`, `{`, `0`...`9`, `-`, `n`, `t`, `f` {
392394
checker.check_json_format(val)!
395+
396+
if checker.checker_idx == checker_end {
397+
checker.checker_idx--
398+
return checker.checker_error('EOF error: braces are not closed')
399+
}
400+
393401
// whitespace
394402
for val[checker.checker_idx] in whitespace_chars {
395403
checker.checker_idx++
396404
}
397405
if val[checker.checker_idx] == `}` {
398406
break
399407
}
400-
if checker.checker_idx >= checker_end - 1 {
408+
409+
if checker.checker_idx == checker_end {
410+
checker.checker_idx--
401411
return checker.checker_error('EOF error: braces are not closed')
402412
}
403413

404414
if val[checker.checker_idx] == `,` {
405415
checker.checker_idx++
416+
417+
if checker.checker_idx == checker_end {
418+
checker.checker_idx--
419+
return checker.checker_error('EOF error: Expecting object key after `,`')
420+
}
421+
406422
for val[checker.checker_idx] in whitespace_chars {
407423
checker.checker_idx++
408424
}
@@ -434,7 +450,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
434450
for val[checker.checker_idx] != `]` {
435451
// skip whitespace
436452
for val[checker.checker_idx] in whitespace_chars {
437-
if checker.checker_idx >= checker_end - 1 {
453+
if checker.checker_idx == checker_end {
454+
checker.checker_idx--
438455
break
439456
}
440457
checker.checker_idx++
@@ -444,7 +461,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
444461
break
445462
}
446463

447-
if checker.checker_idx >= checker_end - 1 {
464+
if checker.checker_idx == checker_end {
465+
checker.checker_idx--
448466
return checker.checker_error('EOF error: array not closed')
449467
}
450468

@@ -457,7 +475,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
457475
if val[checker.checker_idx] == `]` {
458476
break
459477
}
460-
if checker.checker_idx >= checker_end - 1 {
478+
if checker.checker_idx == checker_end {
479+
checker.checker_idx--
461480
return checker.checker_error('EOF error: braces are not closed')
462481
}
463482

@@ -482,7 +501,8 @@ fn (mut checker Decoder) check_json_format(val string) ! {
482501
.string_ {
483502
// check if the JSON string is a valid string
484503

485-
if checker.checker_idx >= checker_end - 1 {
504+
if checker.checker_idx == checker_end {
505+
checker.checker_idx--
486506
return checker.checker_error('EOF error: string not closed')
487507
}
488508

@@ -503,7 +523,7 @@ fn (mut checker Decoder) check_json_format(val string) ! {
503523
// check if the JSON string is a valid unicode escape sequence
504524
escaped_char_last_index := checker.checker_idx + 5
505525

506-
if escaped_char_last_index < checker_end - 1 {
526+
if escaped_char_last_index < checker_end {
507527
// 2 bytes for the unicode escape sequence `\u`
508528
checker.checker_idx += 2
509529

@@ -650,11 +670,11 @@ fn (mut checker Decoder) check_json_format(val string) ! {
650670

651671
actual_value_info_pointer.length = checker.checker_idx + 1 - start_idx_position
652672

653-
if checker.checker_idx < checker_end - 1 {
673+
if checker.checker_idx < checker_end {
654674
checker.checker_idx++
655675
}
656676

657-
for checker.checker_idx < checker_end - 1 && val[checker.checker_idx] !in [`,`, `:`, `}`, `]`] {
677+
for checker.checker_idx < checker_end && val[checker.checker_idx] !in [`,`, `:`, `}`, `]`] {
658678
// get trash characters after the value
659679
if val[checker.checker_idx] !in whitespace_chars {
660680
checker.checker_error('invalid value. Unexpected character after ${value_kind} end')!
@@ -711,6 +731,61 @@ pub fn decode[T](val string) !T {
711731
// decode_value decodes a value from the JSON nodes.
712732
@[manualfree]
713733
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
734+
// Custom Decoders
735+
$if val is StringDecoder {
736+
struct_info := decoder.current_node.value
737+
738+
if struct_info.value_kind == .string_ {
739+
val.from_json_string(decoder.json[struct_info.position + 1..struct_info.position +
740+
struct_info.length - 1]) or {
741+
decoder.decode_error('${typeof(*val).name}: ${err.msg()}')!
742+
}
743+
if decoder.current_node != unsafe { nil } {
744+
decoder.current_node = decoder.current_node.next
745+
}
746+
747+
return
748+
}
749+
}
750+
$if val is NumberDecoder {
751+
struct_info := decoder.current_node.value
752+
753+
if struct_info.value_kind == .number {
754+
val.from_json_number(decoder.json[struct_info.position..struct_info.position +
755+
struct_info.length]) or {
756+
decoder.decode_error('${typeof(*val).name}: ${err.msg()}')!
757+
}
758+
if decoder.current_node != unsafe { nil } {
759+
decoder.current_node = decoder.current_node.next
760+
}
761+
762+
return
763+
}
764+
}
765+
$if val is BooleanDecoder {
766+
struct_info := decoder.current_node.value
767+
768+
if struct_info.value_kind == .boolean {
769+
val.from_json_boolean(decoder.json[struct_info.position] == `t`)
770+
if decoder.current_node != unsafe { nil } {
771+
decoder.current_node = decoder.current_node.next
772+
}
773+
774+
return
775+
}
776+
}
777+
$if val is NullDecoder {
778+
struct_info := decoder.current_node.value
779+
780+
if struct_info.value_kind == .null {
781+
val.from_json_null()
782+
if decoder.current_node != unsafe { nil } {
783+
decoder.current_node = decoder.current_node.next
784+
}
785+
786+
return
787+
}
788+
}
714789
$if T.unaliased_typ is string {
715790
string_info := decoder.current_node.value
716791

@@ -800,50 +875,6 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
800875
} $else $if T.unaliased_typ is $struct {
801876
struct_info := decoder.current_node.value
802877

803-
// Custom Decoders
804-
$if val is StringDecoder {
805-
if struct_info.value_kind == .string_ {
806-
val.from_json_string(decoder.json[struct_info.position + 1..struct_info.position +
807-
struct_info.length - 1])!
808-
if decoder.current_node != unsafe { nil } {
809-
decoder.current_node = decoder.current_node.next
810-
}
811-
812-
return
813-
}
814-
}
815-
$if val is NumberDecoder {
816-
if struct_info.value_kind == .number {
817-
val.from_json_number(decoder.json[struct_info.position..struct_info.position +
818-
struct_info.length])!
819-
if decoder.current_node != unsafe { nil } {
820-
decoder.current_node = decoder.current_node.next
821-
}
822-
823-
return
824-
}
825-
}
826-
$if val is BooleanDecoder {
827-
if struct_info.value_kind == .boolean {
828-
val.from_json_boolean(decoder.json[struct_info.position] == `t`)
829-
if decoder.current_node != unsafe { nil } {
830-
decoder.current_node = decoder.current_node.next
831-
}
832-
833-
return
834-
}
835-
}
836-
$if val is NullDecoder {
837-
if struct_info.value_kind == .null {
838-
val.from_json_null()
839-
if decoder.current_node != unsafe { nil } {
840-
decoder.current_node = decoder.current_node.next
841-
}
842-
843-
return
844-
}
845-
}
846-
847878
// struct field info linked list
848879
mut struct_fields_info := LinkedList[StructFieldInfo]{}
849880

@@ -896,15 +927,19 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
896927

897928
current_field_info = struct_fields_info.head
898929

930+
mut field_used := false
931+
899932
// field loop
900933
for {
901934
if current_field_info == unsafe { nil } {
902-
decoder.current_node = decoder.current_node.next
935+
decoder.current_node = decoder.current_node.next.next // skip value
936+
903937
break
904938
}
905939

906940
if current_field_info.value.is_skip {
907941
if current_field_info.value.is_required == false {
942+
field_used = true
908943
current_field_info = current_field_info.next
909944
continue
910945
}
@@ -913,18 +948,21 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
913948
if current_field_info.value.is_omitempty {
914949
match decoder.current_node.next.value.value_kind {
915950
.null {
951+
field_used = true
916952
current_field_info = current_field_info.next
917953
continue
918954
}
919955
.string_ {
920956
if decoder.current_node.next.value.length == 2 {
957+
field_used = true
921958
current_field_info = current_field_info.next
922959
continue
923960
}
924961
}
925962
.number {
926963
if decoder.json[decoder.current_node.next.value.position] == `0` {
927964
if decoder.current_node.next.value.length == 1 {
965+
field_used = true
928966
current_field_info = current_field_info.next
929967
continue
930968
} else if decoder.current_node.next.value.length == 3 {
@@ -933,6 +971,7 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
933971
decoder.current_node.next.value.position,
934972
float_zero_in_string.str, float_zero_in_string.len) == 0
935973
} {
974+
field_used = true
936975
current_field_info = current_field_info.next
937976
continue
938977
}
@@ -949,6 +988,8 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
949988
vmemcmp(decoder.json.str + key_info.position + 1, current_field_info.value.json_name_ptr,
950989
current_field_info.value.json_name_len) == 0
951990
} {
991+
field_used = true
992+
952993
$for field in T.fields {
953994
if field.name.len == current_field_info.value.field_name_len {
954995
if unsafe {
@@ -962,6 +1003,9 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
9621003
return decoder.decode_error('This should not happen. Please, file a bug. `skip` field should not be processed here without a `required` attribute')
9631004
}
9641005
current_field_info.value.decoded_with_value_info_node = decoder.current_node
1006+
if decoder.current_node != unsafe { nil } {
1007+
decoder.current_node = decoder.current_node.next
1008+
}
9651009
break
9661010
}
9671011

@@ -1008,6 +1052,10 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
10081052
// but options cant be passed to generic functions
10091053
if decoder.current_node.value.value_kind == .null {
10101054
val.$(field.name) = none
1055+
1056+
if decoder.current_node != unsafe { nil } {
1057+
decoder.current_node = decoder.current_node.next
1058+
}
10111059
} else {
10121060
mut unwrapped_val := create_value_from_optional(val.$(field.name)) or {
10131061
return
@@ -1028,6 +1076,12 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
10281076
}
10291077
current_field_info = current_field_info.next
10301078
}
1079+
1080+
if !field_used
1081+
&& decoder.json[key_info.position + 1..key_info.position + key_info.length - 1] != '_type' {
1082+
decoder.decode_error('unknown field `${decoder.json[key_info.position..
1083+
key_info.position + key_info.length]}`')!
1084+
}
10311085
}
10321086

10331087
// check if all required fields are present

0 commit comments

Comments
 (0)