v2 / vlib / x / json2 / tests / decode_nested_object_same_kay_test.v
69 lines · 54 sloc · 2.61 KB · 4b445ced19c155b029d55f2228069c3e467e2e7e
Raw
1import x.json2
2
3// Test for issue #26503: Decoder incorrectly reads nested object fields
4// When a required field appears after unmatched fields with nested objects/arrays,
5// the decoder was incorrectly picking up values from nested structures.
6
7struct Foo {
8 id string @[required]
9 title string @[required]
10}
11
12fn test_decode_with_nested_objects_field_order() {
13 // Test case 1: required fields appear before the nested array
14 s1 := '{"id":"sss","title":"ttt","thumb":[{ "url":"i1.jpg","id":"000"}]}'
15 f1 := json2.decode[Foo](s1)!
16
17 assert f1.id == 'sss', 'f1.id should be "sss" but got "${f1.id}"'
18 assert f1.title == 'ttt', 'f1.title should be "ttt" but got "${f1.title}"'
19
20 // Test case 2: required fields appear after the nested array
21 s2 := '{"title":"ttt","thumb":[{ "url":"i1.jpg","id":"000"}],"id":"sss"}'
22 f2 := json2.decode[Foo](s2)!
23
24 assert f2.id == 'sss', 'f2.id should be "sss" but got "${f2.id}"'
25 assert f2.title == 'ttt', 'f2.title should be "ttt" but got "${f2.title}"'
26
27 // Test case 3: nested array appears between required fields
28 s3 := '{"id":"sss","thumb":[{ "url":"i1.jpg","id":"000"}],"title":"ttt"}'
29 f3 := json2.decode[Foo](s3)!
30
31 assert f3.id == 'sss', 'f3.id should be "sss" but got "${f3.id}"'
32 assert f3.title == 'ttt', 'f3.title should be "ttt" but got "${f3.title}"'
33}
34
35fn test_decode_with_deeply_nested_objects() {
36 // Test with deeply nested structures to ensure complete skipping
37 s := '{"id":"outer","data":{"nested":{"deep":{"id":"inner","title":"inner_title"}}},"title":"outer_title"}'
38 f := json2.decode[Foo](s)!
39
40 assert f.id == 'outer', 'id should be "outer" but got "${f.id}"'
41 assert f.title == 'outer_title', 'title should be "outer_title" but got "${f.title}"'
42}
43
44fn test_decode_with_multiple_nested_arrays() {
45 // Test with multiple nested arrays to ensure complete skipping
46 s := '{"id":"correct","items":[{"id":"a"},{"id":"b"}],"more":[{"id":"c"}],"title":"correct_title"}'
47 f := json2.decode[Foo](s)!
48
49 assert f.id == 'correct', 'id should be "correct" but got "${f.id}"'
50 assert f.title == 'correct_title', 'title should be "correct_title" but got "${f.title}"'
51}
52
53struct BarWithOptional {
54 id string @[required]
55 title ?string
56 extra string
57}
58
59fn test_decode_optional_fields_with_nested() {
60 // Test optional fields work correctly with nested structures
61 s := '{"id":"main","nested":{"title":"nested_title"},"extra":"extra_value"}'
62 b := json2.decode[BarWithOptional](s)!
63
64 assert b.id == 'main', 'id should be "main" but got "${b.id}"'
65 assert b.extra == 'extra_value', 'extra should be "extra_value" but got "${b.extra}"'
66 if title := b.title {
67 assert false, 'title should be none but got "${title}"'
68 }
69}
70