context_spook 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +103 -12
- data/Rakefile +0 -1
- data/bin/context_spook +6 -3
- data/context_spook.gemspec +7 -8
- data/lib/context_spook/generator.rb +75 -45
- data/lib/context_spook/output_context.rb +2 -2
- data/lib/context_spook/toon/encoder.rb +628 -0
- data/lib/context_spook/toon/example.md +36 -66
- data/lib/context_spook/toon.rb +13 -15
- data/lib/context_spook/utils.rb +14 -9
- data/lib/context_spook/version.rb +1 -1
- data/spec/context_spook/generator_spec.rb +63 -2
- data/spec/context_spook/toon_encoder_spec.rb +90 -0
- data/spec/context_spook/toon_spec.rb +15 -16
- data/spec/examples/README.md +79 -0
- data/spec/examples/conversions/keyed-tabular-objects.json +19 -0
- data/spec/examples/conversions/keyed-tabular-objects.toon +4 -0
- data/spec/examples/conversions/nested-field-groups.json +28 -0
- data/spec/examples/conversions/nested-field-groups.toon +4 -0
- data/spec/examples/conversions/tabular-arrays.json +22 -0
- data/spec/examples/conversions/tabular-arrays.toon +4 -0
- data/spec/examples/invalid/delimiter-mismatch.toon +3 -0
- data/spec/examples/invalid/length-mismatch.toon +3 -0
- data/spec/examples/invalid/multiple-root-primitives.toon +2 -0
- data/spec/examples/valid/comments.toon +5 -0
- data/spec/examples/valid/delimiter-scoping.toon +5 -0
- data/spec/examples/valid/mixed-arrays.toon +5 -0
- data/spec/examples/valid/nested-objects.toon +9 -0
- data/spec/examples/valid/objects.toon +6 -0
- data/spec/examples/valid/pipe-delimiter.toon +3 -0
- data/spec/examples/valid/primitive-arrays.toon +3 -0
- data/spec/examples/valid/tab-delimiter.toon +3 -0
- data/spec/fixtures/encode/arrays-nested.json +120 -0
- data/spec/fixtures/encode/arrays-objects.json +160 -0
- data/spec/fixtures/encode/arrays-primitive.json +95 -0
- data/spec/fixtures/encode/arrays-tabular.json +182 -0
- data/spec/fixtures/encode/delimiters.json +214 -0
- data/spec/fixtures/encode/objects-keyed.json +160 -0
- data/spec/fixtures/encode/objects.json +288 -0
- data/spec/fixtures/encode/primitives.json +262 -0
- data/spec/fixtures/encode/whitespace.json +54 -0
- metadata +35 -18
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "4.0",
|
|
3
|
+
"category": "encode",
|
|
4
|
+
"description": "Nested and mixed array encoding – arrays of arrays, mixed type arrays, root arrays",
|
|
5
|
+
"tests": [
|
|
6
|
+
{
|
|
7
|
+
"name": "quotes strings containing delimiters in nested arrays",
|
|
8
|
+
"input": {
|
|
9
|
+
"pairs": [["a", "b"], ["c,d", "e:f", "true"]]
|
|
10
|
+
},
|
|
11
|
+
"expected": "pairs[2]:\n - [2]: a,b\n - [3]: \"c,d\",\"e:f\",\"true\"",
|
|
12
|
+
"specSection": "9.2"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "encodes empty inner arrays",
|
|
16
|
+
"input": {
|
|
17
|
+
"pairs": [[], []]
|
|
18
|
+
},
|
|
19
|
+
"expected": "pairs[2]:\n - [0]:\n - [0]:",
|
|
20
|
+
"specSection": "9.2"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "encodes root-level primitive array",
|
|
24
|
+
"input": ["x", "y", "true", true, 10],
|
|
25
|
+
"expected": "[5]: x,y,\"true\",true,10",
|
|
26
|
+
"specSection": "9.1"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "encodes root-level array of uniform objects in tabular form",
|
|
30
|
+
"input": [{ "id": 1 }, { "id": 2 }],
|
|
31
|
+
"expected": "[2]{id}:\n 1\n 2",
|
|
32
|
+
"specSection": "9.3"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "encodes root-level array of non-uniform objects in list form",
|
|
36
|
+
"input": [{ "id": 1 }, { "id": 2, "name": "Ada" }],
|
|
37
|
+
"expected": "[2]:\n - id: 1\n - id: 2\n name: Ada",
|
|
38
|
+
"specSection": "9.4"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "encodes root-level array mixing primitive, object, and array of objects in list form",
|
|
42
|
+
"input": ["summary", { "id": 1, "name": "Ada" }, [{ "id": 2 }, { "status": "draft" }]],
|
|
43
|
+
"expected": "[3]:\n - summary\n - id: 1\n name: Ada\n - [2]:\n - id: 2\n - status: draft",
|
|
44
|
+
"specSection": "9.4"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "encodes root-level arrays of arrays",
|
|
48
|
+
"input": [[1, 2], []],
|
|
49
|
+
"expected": "[2]:\n - [2]: 1,2\n - [0]:",
|
|
50
|
+
"specSection": "9.2"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "encodes empty root-level array",
|
|
54
|
+
"input": [],
|
|
55
|
+
"expected": "[]",
|
|
56
|
+
"specSection": "9.1"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "uses list form for arrays mixing primitives and objects",
|
|
60
|
+
"input": {
|
|
61
|
+
"items": [1, { "a": 1 }, "text"]
|
|
62
|
+
},
|
|
63
|
+
"expected": "items[3]:\n - 1\n - a: 1\n - text",
|
|
64
|
+
"specSection": "9.4"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "uses list form for arrays mixing objects and arrays",
|
|
68
|
+
"input": {
|
|
69
|
+
"items": [{ "a": 1 }, [1, 2]]
|
|
70
|
+
},
|
|
71
|
+
"expected": "items[2]:\n - a: 1\n - [2]: 1,2",
|
|
72
|
+
"specSection": "9.4"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "quotes hash-leading string as list item",
|
|
76
|
+
"input": {
|
|
77
|
+
"items": ["#x", { "a": 1 }]
|
|
78
|
+
},
|
|
79
|
+
"expected": "items[2]:\n - \"#x\"\n - a: 1",
|
|
80
|
+
"specSection": "7.2"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "uses list form for a tabular-eligible array in list-item position",
|
|
84
|
+
"input": {
|
|
85
|
+
"a": [[{ "x": 1 }, { "x": 2 }]]
|
|
86
|
+
},
|
|
87
|
+
"expected": "a[1]:\n - [2]:\n - x: 1\n - x: 2",
|
|
88
|
+
"specSection": "9.4",
|
|
89
|
+
"note": "A keyless fields-bearing header is valid only at the document root"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "uses list form for an array of arrays in list-item position",
|
|
93
|
+
"input": [
|
|
94
|
+
[
|
|
95
|
+
[
|
|
96
|
+
1
|
|
97
|
+
]
|
|
98
|
+
]
|
|
99
|
+
],
|
|
100
|
+
"expected": "[1]:\n - [1]:\n - [1]: 1",
|
|
101
|
+
"specSection": "9.4"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "uses list form for an array mixing primitives and objects in list-item position",
|
|
105
|
+
"input": {
|
|
106
|
+
"a": [
|
|
107
|
+
[
|
|
108
|
+
1,
|
|
109
|
+
{
|
|
110
|
+
"x": 1
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
2
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"expected": "a[2]:\n - [2]:\n - 1\n - x: 1\n - 2",
|
|
117
|
+
"specSection": "9.4"
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "4.0",
|
|
3
|
+
"category": "encode",
|
|
4
|
+
"description": "Arrays of objects encoding – list form for non-uniform objects and complex structures",
|
|
5
|
+
"tests": [
|
|
6
|
+
{
|
|
7
|
+
"name": "uses list form for objects with different fields",
|
|
8
|
+
"input": {
|
|
9
|
+
"items": [
|
|
10
|
+
{ "id": 1, "name": "First" },
|
|
11
|
+
{ "id": 2, "name": "Second", "extra": true }
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"expected": "items[2]:\n - id: 1\n name: First\n - id: 2\n name: Second\n extra: true",
|
|
15
|
+
"specSection": "9.4"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "preserves field order in list items",
|
|
19
|
+
"input": {
|
|
20
|
+
"items": [
|
|
21
|
+
{ "nums": [1, 2, 3], "name": "Ada" },
|
|
22
|
+
{ "name": "Ada", "nums": [1, 2, 3] }
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"expected": "items[2]:\n - nums[3]: 1,2,3\n name: Ada\n - name: Ada\n nums[3]: 1,2,3",
|
|
26
|
+
"specSection": "10"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "uses list form for objects containing arrays of arrays",
|
|
30
|
+
"input": {
|
|
31
|
+
"items": [
|
|
32
|
+
{ "matrix": [[1, 2], [3, 4]], "name": "grid" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"expected": "items[1]:\n - matrix[2]:\n - [2]: 1,2\n - [2]: 3,4\n name: grid",
|
|
36
|
+
"specSection": "10"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "uses tabular form for a list-item object's first field, with and without sibling fields",
|
|
40
|
+
"input": {
|
|
41
|
+
"items": [
|
|
42
|
+
{ "users": [{ "id": 1, "name": "Ada" }, { "id": 2, "name": "Bob" }], "status": "active" },
|
|
43
|
+
{ "users": [{ "id": 3, "name": "Cy" }, { "id": 4, "name": "Dee" }] }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"expected": "items[2]:\n - users[2]{id,name}:\n 1,Ada\n 2,Bob\n status: active\n - users[2]{id,name}:\n 3,Cy\n 4,Dee",
|
|
47
|
+
"specSection": "10",
|
|
48
|
+
"note": "Tabular header on hyphen line with rows at depth +2 and sibling fields at depth +1"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "uses list form for nested object arrays with mismatched keys",
|
|
52
|
+
"input": {
|
|
53
|
+
"items": [
|
|
54
|
+
{ "users": [{ "id": 1, "name": "Ada" }, { "id": 2 }], "status": "active" }
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"expected": "items[1]:\n - users[2]:\n - id: 1\n name: Ada\n - id: 2\n status: active",
|
|
58
|
+
"specSection": "10"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "places empty arrays on the hyphen line when first and at field depth when later",
|
|
62
|
+
"input": {
|
|
63
|
+
"items": [
|
|
64
|
+
{ "data": [], "name": "Ada" },
|
|
65
|
+
{ "name": "Bob", "data": [] }
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"expected": "items[2]:\n - data: []\n name: Ada\n - name: Bob\n data: []",
|
|
69
|
+
"specSection": "10"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "uses field order from first object for tabular headers",
|
|
73
|
+
"input": {
|
|
74
|
+
"items": [
|
|
75
|
+
{ "a": 1, "b": 2, "c": 3 },
|
|
76
|
+
{ "c": 30, "b": 20, "a": 10 }
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"expected": "items[2]{a,b,c}:\n 1,2,3\n 10,20,30",
|
|
80
|
+
"specSection": "9.3"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "uses list form when one object has nested field",
|
|
84
|
+
"input": {
|
|
85
|
+
"items": [
|
|
86
|
+
{ "id": 1, "data": "string" },
|
|
87
|
+
{ "id": 2, "data": { "nested": true } }
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"expected": "items[2]:\n - id: 1\n data: string\n - id: 2\n data:\n nested: true",
|
|
91
|
+
"specSection": "9.4"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "uses list form for arrays containing empty objects",
|
|
95
|
+
"input": {
|
|
96
|
+
"items": [{}, {}]
|
|
97
|
+
},
|
|
98
|
+
"expected": "items[2]:\n -\n -",
|
|
99
|
+
"specSection": "9.4",
|
|
100
|
+
"note": "Empty objects are excluded from tabular detection (§9.3), so the array uses list form with bare hyphen markers (§10)"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "encodes a keyed-eligible object in a tabular column as a nested field group",
|
|
104
|
+
"input": {
|
|
105
|
+
"a": [
|
|
106
|
+
{
|
|
107
|
+
"t": {
|
|
108
|
+
"p": {
|
|
109
|
+
"x": 1
|
|
110
|
+
},
|
|
111
|
+
"q": {
|
|
112
|
+
"x": 2
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"other": 9
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"expected": "a[1]{t{p{x},q{x}},other}:\n 1,2,9",
|
|
120
|
+
"specSection": "9.5",
|
|
121
|
+
"note": "Keyed tabular form is mandated in object-field and root positions, not in a column",
|
|
122
|
+
"minSpecVersion": "4.1"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "places an empty object first field on the hyphen line",
|
|
126
|
+
"input": {
|
|
127
|
+
"items": [
|
|
128
|
+
{
|
|
129
|
+
"a": {},
|
|
130
|
+
"b": 1
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"expected": "items[1]:\n - a:\n b: 1",
|
|
135
|
+
"specSection": "10"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "uses tabular form for a later field of a list-item object",
|
|
139
|
+
"input": {
|
|
140
|
+
"items": [
|
|
141
|
+
{
|
|
142
|
+
"id": 1,
|
|
143
|
+
"users": [
|
|
144
|
+
{
|
|
145
|
+
"id": 1,
|
|
146
|
+
"name": "Ada"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": 2,
|
|
150
|
+
"name": "Bob"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
"expected": "items[1]:\n - id: 1\n users[2]{id,name}:\n 1,Ada\n 2,Bob",
|
|
157
|
+
"specSection": "10"
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "4.0",
|
|
3
|
+
"category": "encode",
|
|
4
|
+
"description": "Primitive array encoding – inline arrays of strings, numbers, booleans",
|
|
5
|
+
"tests": [
|
|
6
|
+
{
|
|
7
|
+
"name": "encodes mixed primitive arrays inline",
|
|
8
|
+
"input": {
|
|
9
|
+
"data": ["x", "y", true, 10]
|
|
10
|
+
},
|
|
11
|
+
"expected": "data[4]: x,y,true,10",
|
|
12
|
+
"specSection": "9.1"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "encodes empty arrays",
|
|
16
|
+
"input": {
|
|
17
|
+
"items": []
|
|
18
|
+
},
|
|
19
|
+
"expected": "items: []",
|
|
20
|
+
"specSection": "9.1"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "encodes empty string keys for inline arrays",
|
|
24
|
+
"input": {
|
|
25
|
+
"": [1, 2, 3]
|
|
26
|
+
},
|
|
27
|
+
"expected": "\"\"[3]: 1,2,3",
|
|
28
|
+
"specSection": "9.1"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "encodes empty string keys for empty arrays",
|
|
32
|
+
"input": {
|
|
33
|
+
"": []
|
|
34
|
+
},
|
|
35
|
+
"expected": "\"\": []",
|
|
36
|
+
"specSection": "9.1"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "encodes empty string in single-item array",
|
|
40
|
+
"input": {
|
|
41
|
+
"items": [""]
|
|
42
|
+
},
|
|
43
|
+
"expected": "items[1]: \"\"",
|
|
44
|
+
"specSection": "9.1"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "encodes empty string in multi-item array",
|
|
48
|
+
"input": {
|
|
49
|
+
"items": ["a", "", "b"]
|
|
50
|
+
},
|
|
51
|
+
"expected": "items[3]: a,\"\",b",
|
|
52
|
+
"specSection": "9.1"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "encodes whitespace-only strings in arrays",
|
|
56
|
+
"input": {
|
|
57
|
+
"items": [" ", " "]
|
|
58
|
+
},
|
|
59
|
+
"expected": "items[2]: \" \",\" \"",
|
|
60
|
+
"specSection": "9.1"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "quotes array strings with comma",
|
|
64
|
+
"input": {
|
|
65
|
+
"items": ["a", "b,c", "d:e"]
|
|
66
|
+
},
|
|
67
|
+
"expected": "items[3]: a,\"b,c\",\"d:e\"",
|
|
68
|
+
"specSection": "9.1"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "quotes strings that look like literals or numbers in arrays",
|
|
72
|
+
"input": {
|
|
73
|
+
"items": ["x", "true", "42", "-3.14"]
|
|
74
|
+
},
|
|
75
|
+
"expected": "items[4]: x,\"true\",\"42\",\"-3.14\"",
|
|
76
|
+
"specSection": "9.1"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "quotes strings with structural meanings in arrays",
|
|
80
|
+
"input": {
|
|
81
|
+
"items": ["[5", "x]", "- item", "{key", "y}"]
|
|
82
|
+
},
|
|
83
|
+
"expected": "items[5]: \"[5\",\"x]\",\"- item\",\"{key\",\"y}\"",
|
|
84
|
+
"specSection": "9.1"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "quotes hash-leading string in inline array",
|
|
88
|
+
"input": {
|
|
89
|
+
"tags": ["#a", "b"]
|
|
90
|
+
},
|
|
91
|
+
"expected": "tags[2]: \"#a\",b",
|
|
92
|
+
"specSection": "7.2"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "4.0",
|
|
3
|
+
"category": "encode",
|
|
4
|
+
"description": "Tabular array encoding – arrays of uniform objects with primitive values",
|
|
5
|
+
"tests": [
|
|
6
|
+
{
|
|
7
|
+
"name": "encodes arrays of uniform objects in tabular form",
|
|
8
|
+
"input": {
|
|
9
|
+
"items": [
|
|
10
|
+
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
|
11
|
+
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"expected": "items[2]{sku,qty,price}:\n A1,2,9.99\n B2,1,14.5",
|
|
15
|
+
"specSection": "9.3"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "encodes null values in tabular form",
|
|
19
|
+
"input": {
|
|
20
|
+
"items": [
|
|
21
|
+
{ "id": 1, "value": null },
|
|
22
|
+
{ "id": 2, "value": "test" }
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"expected": "items[2]{id,value}:\n 1,null\n 2,test",
|
|
26
|
+
"specSection": "9.3"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "quotes strings containing delimiters in tabular rows",
|
|
30
|
+
"input": {
|
|
31
|
+
"items": [
|
|
32
|
+
{ "sku": "A,1", "desc": "cool", "qty": 2 },
|
|
33
|
+
{ "sku": "B2", "desc": "wip: test", "qty": 1 }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"expected": "items[2]{sku,desc,qty}:\n \"A,1\",cool,2\n B2,\"wip: test\",1",
|
|
37
|
+
"specSection": "9.3"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "quotes ambiguous strings in tabular rows",
|
|
41
|
+
"input": {
|
|
42
|
+
"items": [
|
|
43
|
+
{ "id": 1, "status": "true" },
|
|
44
|
+
{ "id": 2, "status": "false" }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"expected": "items[2]{id,status}:\n 1,\"true\"\n 2,\"false\"",
|
|
48
|
+
"specSection": "9.3"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "encodes tabular arrays with keys needing quotes",
|
|
52
|
+
"input": {
|
|
53
|
+
"items": [
|
|
54
|
+
{ "order:id": 1, "full name": "Ada" },
|
|
55
|
+
{ "order:id": 2, "full name": "Bob" }
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"expected": "items[2]{\"order:id\",\"full name\"}:\n 1,Ada\n 2,Bob",
|
|
59
|
+
"specSection": "9.3"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "encodes tabular arrays with empty string keys",
|
|
63
|
+
"input": {
|
|
64
|
+
"": [
|
|
65
|
+
{ "id": 1, "name": "Ada" },
|
|
66
|
+
{ "id": 2, "name": "Bob" }
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"expected": "\"\"[2]{id,name}:\n 1,Ada\n 2,Bob",
|
|
70
|
+
"specSection": "9.3"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "quotes hash-leading string in tabular cell",
|
|
74
|
+
"input": {
|
|
75
|
+
"items": [{ "tag": "#a" }, { "tag": "b" }]
|
|
76
|
+
},
|
|
77
|
+
"expected": "items[2]{tag}:\n \"#a\"\n b",
|
|
78
|
+
"specSection": "7.2",
|
|
79
|
+
"note": "Unquoted, the first row would read as a comment line on decode"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "collapses a uniform nested object column into a nested field group",
|
|
83
|
+
"input": {
|
|
84
|
+
"orders": [
|
|
85
|
+
{ "id": 1, "customer": { "name": "Ada", "country": "DK" }, "total": 99 },
|
|
86
|
+
{ "id": 2, "customer": { "country": "UK", "name": "Bob" }, "total": 149 }
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"expected": "orders[2]{id,customer{name,country},total}:\n 1,Ada,DK,99\n 2,Bob,UK,149",
|
|
90
|
+
"specSection": "9.3"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "collapses sibling nested field groups with depth-first row layout",
|
|
94
|
+
"input": {
|
|
95
|
+
"shipments": [
|
|
96
|
+
{ "id": "s1", "sender": { "name": "ACME", "city": "Berlin" }, "receiver": { "name": "Globex", "city": "Oslo" } }
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"expected": "shipments[1]{id,sender{name,city},receiver{name,city}}:\n s1,ACME,Berlin,Globex,Oslo",
|
|
100
|
+
"specSection": "9.3"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "collapses nested field groups recursively without a depth cap",
|
|
104
|
+
"input": {
|
|
105
|
+
"items": [
|
|
106
|
+
{ "id": 1, "geo": { "point": { "lat": 1.5, "lon": 2.5 } } },
|
|
107
|
+
{ "id": 2, "geo": { "point": { "lat": 3, "lon": 4 } } }
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"expected": "items[2]{id,geo{point{lat,lon}}}:\n 1,1.5,2.5\n 2,3,4",
|
|
111
|
+
"specSection": "9.3"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "uses the active delimiter inside nested field groups",
|
|
115
|
+
"input": {
|
|
116
|
+
"orders": [
|
|
117
|
+
{ "id": 1, "customer": { "name": "Ada", "country": "DK" }, "total": 99 },
|
|
118
|
+
{ "id": 2, "customer": { "name": "Bob", "country": "UK" }, "total": 149 }
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"options": { "delimiter": "|" },
|
|
122
|
+
"expected": "orders[2|]{id|customer{name|country}|total}:\n 1|Ada|DK|99\n 2|Bob|UK|149",
|
|
123
|
+
"specSection": "9.3"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "quotes subfield names inside nested field groups per key encoding",
|
|
127
|
+
"input": {
|
|
128
|
+
"items": [
|
|
129
|
+
{ "id": 1, "customer": { "full name": "Ada", "country": "UK" } }
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
"expected": "items[1]{id,customer{\"full name\",country}}:\n 1,Ada,UK",
|
|
133
|
+
"specSection": "9.3"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "falls back to list form when nested object keys differ per row",
|
|
137
|
+
"input": {
|
|
138
|
+
"entries": [
|
|
139
|
+
{ "id": 1, "meta": { "a": 1 } },
|
|
140
|
+
{ "id": 2, "meta": { "b": 2 } }
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
"expected": "entries[2]:\n - id: 1\n meta:\n a: 1\n - id: 2\n meta:\n b: 2",
|
|
144
|
+
"specSection": "9.3",
|
|
145
|
+
"note": "The meta column is not nested-uniform (differing key sets), so the whole array uses §9.4"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "falls back to list form when a column mixes null and objects",
|
|
149
|
+
"input": {
|
|
150
|
+
"orders": [
|
|
151
|
+
{ "id": 1, "customer": { "name": "Ada" } },
|
|
152
|
+
{ "id": 2, "customer": null }
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
"expected": "orders[2]:\n - id: 1\n customer:\n name: Ada\n - id: 2\n customer: null",
|
|
156
|
+
"specSection": "9.3",
|
|
157
|
+
"note": "A null cell is a primitive, so the customer column is neither uniform-primitive nor nested-uniform"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "falls back to list form when a nested object contains an array",
|
|
161
|
+
"input": {
|
|
162
|
+
"orders": [
|
|
163
|
+
{ "id": 1, "customer": { "name": "Ada", "tags": ["x"] } }
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
"expected": "orders[1]:\n - id: 1\n customer:\n name: Ada\n tags[1]: x",
|
|
167
|
+
"specSection": "9.3",
|
|
168
|
+
"note": "Array values disqualify a column; rows must contain only primitive cells"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"name": "falls back to list form when a nested column contains an empty object",
|
|
172
|
+
"input": {
|
|
173
|
+
"items": [
|
|
174
|
+
{ "id": 1, "meta": {} }
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
"expected": "items[1]:\n - id: 1\n meta:",
|
|
178
|
+
"specSection": "9.3",
|
|
179
|
+
"note": "Nested-uniform requires non-empty objects, mirroring the empty-object exclusion for elements"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|