chore(release): prepare public source release
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
{
|
||||
"version": "3.0",
|
||||
"category": "decode",
|
||||
"description": "Nested and mixed array decoding - list format, arrays of arrays, root arrays, mixed types",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses list arrays for non-uniform objects",
|
||||
"input": "items[2]:\n - id: 1\n name: First\n - id: 2\n name: Second\n extra: true",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "First" },
|
||||
{ "id": 2, "name": "Second", "extra": true }
|
||||
]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses list arrays with empty items",
|
||||
"input": "items[3]:\n - first\n - second\n -",
|
||||
"expected": {
|
||||
"items": ["first", "second", {}]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses list arrays with deeply nested objects",
|
||||
"input": "items[2]:\n - properties:\n state:\n type: string\n - id: 2",
|
||||
"expected": {
|
||||
"items": [
|
||||
{
|
||||
"properties": {
|
||||
"state": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "parses list arrays containing objects with nested properties",
|
||||
"input": "items[1]:\n - id: 1\n nested:\n x: 1",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "nested": { "x": 1 } }
|
||||
]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses list items whose first field is a tabular array",
|
||||
"input": "items[1]:\n - users[2]{id,name}:\n 1,Ada\n 2,Bob\n status: active",
|
||||
"expected": {
|
||||
"items": [
|
||||
{
|
||||
"users": [
|
||||
{ "id": 1, "name": "Ada" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
],
|
||||
"status": "active"
|
||||
}
|
||||
]
|
||||
},
|
||||
"specSection": "10",
|
||||
"note": "Canonical encoding: tabular header on hyphen line, rows at depth +2, sibling fields at depth +1"
|
||||
},
|
||||
{
|
||||
"name": "parses single-field list-item object with tabular array",
|
||||
"input": "items[1]:\n - users[2]{id,name}:\n 1,Ada\n 2,Bob",
|
||||
"expected": {
|
||||
"items": [
|
||||
{
|
||||
"users": [
|
||||
{ "id": 1, "name": "Ada" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"specSection": "10",
|
||||
"note": "Single-field list-item object: only the tabular array, no sibling fields"
|
||||
},
|
||||
{
|
||||
"name": "parses objects containing arrays (including empty arrays) in list format",
|
||||
"input": "items[1]:\n - name: Ada\n data[0]:",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "name": "Ada", "data": [] }
|
||||
]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses arrays of arrays within objects",
|
||||
"input": "items[1]:\n - matrix[2]:\n - [2]: 1,2\n - [2]: 3,4\n name: grid",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "matrix": [[1, 2], [3, 4]], "name": "grid" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses nested arrays of primitives",
|
||||
"input": "pairs[2]:\n - [2]: a,b\n - [2]: c,d",
|
||||
"expected": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted strings and mixed lengths in nested arrays",
|
||||
"input": "pairs[2]:\n - [2]: a,b\n - [3]: \"c,d\",\"e:f\",\"true\"",
|
||||
"expected": {
|
||||
"pairs": [["a", "b"], ["c,d", "e:f", "true"]]
|
||||
},
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses empty inner arrays",
|
||||
"input": "pairs[2]:\n - [0]:\n - [0]:",
|
||||
"expected": {
|
||||
"pairs": [[], []]
|
||||
},
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses mixed-length inner arrays",
|
||||
"input": "pairs[2]:\n - [1]: 1\n - [2]: 2,3",
|
||||
"expected": {
|
||||
"pairs": [[1], [2, 3]]
|
||||
},
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level primitive array inline",
|
||||
"input": "[5]: x,y,\"true\",true,10",
|
||||
"expected": ["x", "y", "true", true, 10],
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array of uniform objects in tabular format",
|
||||
"input": "[2]{id}:\n 1\n 2",
|
||||
"expected": [{ "id": 1 }, { "id": 2 }],
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array of non-uniform objects in list format",
|
||||
"input": "[2]:\n - id: 1\n - id: 2\n name: Ada",
|
||||
"expected": [{ "id": 1 }, { "id": 2, "name": "Ada" }],
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array mixing primitive, object, and array of objects in list format",
|
||||
"input": "[3]:\n - summary\n - id: 1\n name: Ada\n - [2]:\n - id: 2\n - status: draft",
|
||||
"expected": ["summary", { "id": 1, "name": "Ada" }, [{ "id": 2 }, { "status": "draft" }]],
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array of arrays",
|
||||
"input": "[2]:\n - [2]: 1,2\n - [0]:",
|
||||
"expected": [[1, 2], []],
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "parses empty root-level array",
|
||||
"input": "[0]:",
|
||||
"expected": [],
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses complex mixed object with arrays and nested objects",
|
||||
"input": "user:\n id: 123\n name: Ada\n tags[2]: reading,gaming\n active: true\n prefs[0]:",
|
||||
"expected": {
|
||||
"user": {
|
||||
"id": 123,
|
||||
"name": "Ada",
|
||||
"tags": ["reading", "gaming"],
|
||||
"active": true,
|
||||
"prefs": []
|
||||
}
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses arrays mixing primitives, objects, and strings in list format",
|
||||
"input": "items[3]:\n - 1\n - a: 1\n - text",
|
||||
"expected": {
|
||||
"items": [1, { "a": 1 }, "text"]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses arrays mixing objects and arrays",
|
||||
"input": "items[2]:\n - a: 1\n - [2]: 1,2",
|
||||
"expected": {
|
||||
"items": [{ "a": 1 }, [1, 2]]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with list array format",
|
||||
"input": "\"x-items\"[2]:\n - id: 1\n - id: 2",
|
||||
"expected": {
|
||||
"x-items": [
|
||||
{ "id": 1 },
|
||||
{ "id": 2 }
|
||||
]
|
||||
},
|
||||
"specSection": "9.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Primitive array decoding - inline arrays of strings, numbers, booleans, quoted strings",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses string arrays inline",
|
||||
"input": "tags[3]: reading,gaming,coding",
|
||||
"expected": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses number arrays inline",
|
||||
"input": "nums[3]: 1,2,3",
|
||||
"expected": {
|
||||
"nums": [1, 2, 3]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses mixed primitive arrays inline",
|
||||
"input": "data[4]: x,y,true,10",
|
||||
"expected": {
|
||||
"data": ["x", "y", true, 10]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses empty arrays",
|
||||
"input": "items[0]:",
|
||||
"expected": {
|
||||
"items": []
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses single-item array with empty string",
|
||||
"input": "items[1]: \"\"",
|
||||
"expected": {
|
||||
"items": [""]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses multi-item array with empty string",
|
||||
"input": "items[3]: a,\"\",b",
|
||||
"expected": {
|
||||
"items": ["a", "", "b"]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses whitespace-only strings in arrays",
|
||||
"input": "items[2]: \" \",\" \"",
|
||||
"expected": {
|
||||
"items": [" ", " "]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses strings with delimiters in arrays",
|
||||
"input": "items[3]: a,\"b,c\",\"d:e\"",
|
||||
"expected": {
|
||||
"items": ["a", "b,c", "d:e"]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses strings that look like primitives when quoted",
|
||||
"input": "items[4]: x,\"true\",\"42\",\"-3.14\"",
|
||||
"expected": {
|
||||
"items": ["x", "true", "42", "-3.14"]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses strings with structural tokens in arrays",
|
||||
"input": "items[3]: \"[5]\",\"- item\",\"{key}\"",
|
||||
"expected": {
|
||||
"items": ["[5]", "- item", "{key}"]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with inline array",
|
||||
"input": "\"my-key\"[3]: 1,2,3",
|
||||
"expected": {
|
||||
"my-key": [1, 2, 3]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted empty string key with inline array",
|
||||
"input": "\"\"[3]: 1,2,3",
|
||||
"expected": {
|
||||
"": [1, 2, 3]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key containing brackets with inline array",
|
||||
"input": "\"key[test]\"[3]: 1,2,3",
|
||||
"expected": {
|
||||
"key[test]": [1, 2, 3]
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with empty array",
|
||||
"input": "\"x-custom\"[0]:",
|
||||
"expected": {
|
||||
"x-custom": []
|
||||
},
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted empty string key with empty array",
|
||||
"input": "\"\"[0]:",
|
||||
"expected": {
|
||||
"": []
|
||||
},
|
||||
"specSection": "9.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Tabular array decoding - parsing arrays of uniform objects with headers",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses tabular arrays of uniform objects",
|
||||
"input": "items[2]{sku,qty,price}:\n A1,2,9.99\n B2,1,14.5",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses nulls and quoted values in tabular rows",
|
||||
"input": "items[2]{id,value}:\n 1,null\n 2,\"test\"",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "value": null },
|
||||
{ "id": 2, "value": "test" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted colon in tabular row as data",
|
||||
"input": "items[2]{id,note}:\n 1,\"a:b\"\n 2,\"c:d\"",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "note": "a:b" },
|
||||
{ "id": 2, "note": "c:d" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted header keys in tabular arrays",
|
||||
"input": "items[2]{\"order:id\",\"full name\"}:\n 1,Ada\n 2,Bob",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "order:id": 1, "full name": "Ada" },
|
||||
{ "order:id": 2, "full name": "Bob" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with tabular array format",
|
||||
"input": "\"x-items\"[2]{id,name}:\n 1,Ada\n 2,Bob",
|
||||
"expected": {
|
||||
"x-items": [
|
||||
{ "id": 1, "name": "Ada" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted empty string key with tabular array format",
|
||||
"input": "\"\"[2]{id,name}:\n 1,Ada\n 2,Bob",
|
||||
"expected": {
|
||||
"": [
|
||||
{ "id": 1, "name": "Ada" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
},
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "treats unquoted colon as terminator for tabular rows and start of key-value pair",
|
||||
"input": "items[2]{id,name}:\n 1,Alice\n 2,Bob\ncount: 2",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "Alice" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
],
|
||||
"count": 2
|
||||
},
|
||||
"specSection": "9.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Blank line handling - strict mode errors on blank lines inside arrays, accepts blank lines outside arrays",
|
||||
"tests": [
|
||||
{
|
||||
"name": "throws on blank line inside list array",
|
||||
"input": "items[3]:\n - a\n\n - b\n - c",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.4"
|
||||
},
|
||||
{
|
||||
"name": "throws on blank line inside tabular array",
|
||||
"input": "items[2]{id}:\n 1\n\n 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.4"
|
||||
},
|
||||
{
|
||||
"name": "throws on multiple blank lines inside array",
|
||||
"input": "items[2]:\n - a\n\n\n - b",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.4"
|
||||
},
|
||||
{
|
||||
"name": "throws on blank line with spaces inside array",
|
||||
"input": "items[2]:\n - a\n \n - b",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.4"
|
||||
},
|
||||
{
|
||||
"name": "throws on blank line in nested list array",
|
||||
"input": "outer[2]:\n - inner[2]:\n - a\n\n - b\n - x",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.4"
|
||||
},
|
||||
{
|
||||
"name": "accepts blank line between root-level fields",
|
||||
"input": "a: 1\n\nb: 2",
|
||||
"expected": {
|
||||
"a": 1,
|
||||
"b": 2
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts trailing newline at end of file",
|
||||
"input": "a: 1\n",
|
||||
"expected": {
|
||||
"a": 1
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts multiple trailing newlines",
|
||||
"input": "a: 1\n\n\n",
|
||||
"expected": {
|
||||
"a": 1
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts blank line after array ends",
|
||||
"input": "items[1]:\n - a\n\nb: 2",
|
||||
"expected": {
|
||||
"items": ["a"],
|
||||
"b": 2
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts blank line between nested object fields",
|
||||
"input": "a:\n b: 1\n\n c: 2",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": 1,
|
||||
"c": 2
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "ignores blank lines inside list array when strict=false",
|
||||
"input": "items[3]:\n - a\n\n - b\n - c",
|
||||
"expected": {
|
||||
"items": ["a", "b", "c"]
|
||||
},
|
||||
"options": {
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "ignores blank lines inside tabular array when strict=false",
|
||||
"input": "items[2]{id,name}:\n 1,Alice\n\n 2,Bob",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "Alice" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "ignores multiple blank lines in arrays when strict=false",
|
||||
"input": "items[2]:\n - a\n\n\n - b",
|
||||
"expected": {
|
||||
"items": ["a", "b"]
|
||||
},
|
||||
"options": {
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "12"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Delimiter decoding - tab and pipe delimiter parsing, delimiter-aware value splitting",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses primitive arrays with tab delimiter",
|
||||
"input": "tags[3\t]: reading\tgaming\tcoding",
|
||||
"expected": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses primitive arrays with pipe delimiter",
|
||||
"input": "tags[3|]: reading|gaming|coding",
|
||||
"expected": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses primitive arrays with comma delimiter",
|
||||
"input": "tags[3]: reading,gaming,coding",
|
||||
"expected": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses tabular arrays with tab delimiter",
|
||||
"input": "items[2\t]{sku\tqty\tprice}:\n A1\t2\t9.99\n B2\t1\t14.5",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses tabular arrays with pipe delimiter",
|
||||
"input": "items[2|]{sku|qty|price}:\n A1|2|9.99\n B2|1|14.5",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses nested arrays with tab delimiter",
|
||||
"input": "pairs[2\t]:\n - [2\t]: a\tb\n - [2\t]: c\td",
|
||||
"expected": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses nested arrays with pipe delimiter",
|
||||
"input": "pairs[2|]:\n - [2|]: a|b\n - [2|]: c|d",
|
||||
"expected": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses nested arrays inside list items with default comma delimiter",
|
||||
"input": "items[1\t]:\n - tags[3]: a,b,c",
|
||||
"expected": {
|
||||
"items": [{ "tags": ["a", "b", "c"] }]
|
||||
},
|
||||
"specSection": "11",
|
||||
"note": "Parent uses tab, nested defaults to comma"
|
||||
},
|
||||
{
|
||||
"name": "parses nested arrays inside list items with default comma delimiter when parent uses pipe",
|
||||
"input": "items[1|]:\n - tags[3]: a,b,c",
|
||||
"expected": {
|
||||
"items": [{ "tags": ["a", "b", "c"] }]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array with tab delimiter",
|
||||
"input": "[3\t]: x\ty\tz",
|
||||
"expected": ["x", "y", "z"],
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array with pipe delimiter",
|
||||
"input": "[3|]: x|y|z",
|
||||
"expected": ["x", "y", "z"],
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array of objects with tab delimiter",
|
||||
"input": "[2\t]{id}:\n 1\n 2",
|
||||
"expected": [{ "id": 1 }, { "id": 2 }],
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level array of objects with pipe delimiter",
|
||||
"input": "[2|]{id}:\n 1\n 2",
|
||||
"expected": [{ "id": 1 }, { "id": 2 }],
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses values containing tab delimiter when quoted",
|
||||
"input": "items[3\t]: a\t\"b\\tc\"\td",
|
||||
"expected": {
|
||||
"items": ["a", "b\tc", "d"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses values containing pipe delimiter when quoted",
|
||||
"input": "items[3|]: a|\"b|c\"|d",
|
||||
"expected": {
|
||||
"items": ["a", "b|c", "d"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not split on commas when using tab delimiter",
|
||||
"input": "items[2\t]: a,b\tc,d",
|
||||
"expected": {
|
||||
"items": ["a,b", "c,d"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not split on commas when using pipe delimiter",
|
||||
"input": "items[2|]: a,b|c,d",
|
||||
"expected": {
|
||||
"items": ["a,b", "c,d"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses tabular values containing comma with comma delimiter",
|
||||
"input": "items[2]{id,note}:\n 1,\"a,b\"\n 2,\"c,d\"",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "note": "a,b" },
|
||||
{ "id": 2, "note": "c,d" }
|
||||
]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not require quoting commas with tab delimiter",
|
||||
"input": "items[2\t]{id\tnote}:\n 1\ta,b\n 2\tc,d",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "note": "a,b" },
|
||||
{ "id": 2, "note": "c,d" }
|
||||
]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not require quoting commas in object values",
|
||||
"input": "note: a,b",
|
||||
"expected": {
|
||||
"note": "a,b"
|
||||
},
|
||||
"specSection": "11",
|
||||
"note": "Object values don't require comma quoting regardless of delimiter"
|
||||
},
|
||||
{
|
||||
"name": "object values in list items follow document delimiter",
|
||||
"input": "items[2\t]:\n - status: a,b\n - status: c,d",
|
||||
"expected": {
|
||||
"items": [{ "status": "a,b" }, { "status": "c,d" }]
|
||||
},
|
||||
"specSection": "11",
|
||||
"note": "Active delimiter is tab, but object values use document delimiter for quoting"
|
||||
},
|
||||
{
|
||||
"name": "object values with comma must be quoted when document delimiter is comma",
|
||||
"input": "items[2]:\n - status: \"a,b\"\n - status: \"c,d\"",
|
||||
"expected": {
|
||||
"items": [{ "status": "a,b" }, { "status": "c,d" }]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses nested array values containing pipe delimiter",
|
||||
"input": "pairs[1|]:\n - [2|]: a|\"b|c\"",
|
||||
"expected": {
|
||||
"pairs": [["a", "b|c"]]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses nested array values containing tab delimiter",
|
||||
"input": "pairs[1\t]:\n - [2\t]: a\t\"b\\tc\"",
|
||||
"expected": {
|
||||
"pairs": [["a", "b\tc"]]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "preserves quoted ambiguity with pipe delimiter",
|
||||
"input": "items[3|]: \"true\"|\"42\"|\"-3.14\"",
|
||||
"expected": {
|
||||
"items": ["true", "42", "-3.14"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "preserves quoted ambiguity with tab delimiter",
|
||||
"input": "items[3\t]: \"true\"\t\"42\"\t\"-3.14\"",
|
||||
"expected": {
|
||||
"items": ["true", "42", "-3.14"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses structural-looking strings when quoted with pipe delimiter",
|
||||
"input": "items[3|]: \"[5]\"|\"{key}\"|\"- item\"",
|
||||
"expected": {
|
||||
"items": ["[5]", "{key}", "- item"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses structural-looking strings when quoted with tab delimiter",
|
||||
"input": "items[3\t]: \"[5]\"\t\"{key}\"\t\"- item\"",
|
||||
"expected": {
|
||||
"items": ["[5]", "{key}", "- item"]
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "parses tabular headers with keys containing the active delimiter",
|
||||
"input": "items[2|]{\"a|b\"}:\n 1\n 2",
|
||||
"expected": {
|
||||
"items": [{ "a|b": 1 }, { "a|b": 2 }]
|
||||
},
|
||||
"specSection": "11"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Strict mode indentation validation - non-multiple indentation, tab characters, custom indent sizes",
|
||||
"tests": [
|
||||
{
|
||||
"name": "throws on object field with non-multiple indentation (3 spaces with indent=2)",
|
||||
"input": "a:\n b: 1",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"indent": 2,
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "throws on list item with non-multiple indentation (3 spaces with indent=2)",
|
||||
"input": "items[2]:\n - id: 1\n - id: 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"indent": 2,
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "throws on non-multiple indentation with custom indent=4 (3 spaces)",
|
||||
"input": "a:\n b: 1",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"indent": 4,
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "accepts correct indentation with custom indent size (4 spaces with indent=4)",
|
||||
"input": "a:\n b: 1",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": 1
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"indent": 4,
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "throws on tab character used in indentation",
|
||||
"input": "a:\n\tb: 1",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "throws on mixed tabs and spaces in indentation",
|
||||
"input": "a:\n \tb: 1",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "throws on tab at start of line",
|
||||
"input": "\ta: 1",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.3"
|
||||
},
|
||||
{
|
||||
"name": "accepts tabs in quoted string values",
|
||||
"input": "text: \"hello\tworld\"",
|
||||
"expected": {
|
||||
"text": "hello\tworld"
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts tabs in quoted keys",
|
||||
"input": "\"key\ttab\": value",
|
||||
"expected": {
|
||||
"key\ttab": "value"
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts tabs in quoted array elements",
|
||||
"input": "items[2]: \"a\tb\",\"c\td\"",
|
||||
"expected": {
|
||||
"items": ["a\tb", "c\td"]
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts non-multiple indentation when strict=false",
|
||||
"input": "a:\n b: 1",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": 1
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"indent": 2,
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "accepts deeply nested non-multiples when strict=false",
|
||||
"input": "a:\n b:\n c: 1",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"indent": 2,
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "parses empty lines without validation errors",
|
||||
"input": "a: 1\n\nb: 2",
|
||||
"expected": {
|
||||
"a": 1,
|
||||
"b": 2
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "parses root-level content (0 indentation) as always valid",
|
||||
"input": "a: 1\nb: 2\nc: 3",
|
||||
"expected": {
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "parses lines with only spaces without validation if empty",
|
||||
"input": "a: 1\n \nb: 2",
|
||||
"expected": {
|
||||
"a": 1,
|
||||
"b": 2
|
||||
},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "12"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Number decoding edge cases - trailing zeros, exponent forms, negative zero",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses number with trailing zeros in fractional part",
|
||||
"input": "value: 1.5000",
|
||||
"expected": {
|
||||
"value": 1.5
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Decoders accept trailing zeros; numeric value is 1.5"
|
||||
},
|
||||
{
|
||||
"name": "parses negative number with positive exponent",
|
||||
"input": "value: -1E+03",
|
||||
"expected": {
|
||||
"value": -1000
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Exponent forms are accepted by decoders"
|
||||
},
|
||||
{
|
||||
"name": "parses lowercase exponent",
|
||||
"input": "value: 2.5e2",
|
||||
"expected": {
|
||||
"value": 250
|
||||
},
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses uppercase exponent with negative sign",
|
||||
"input": "value: 3E-02",
|
||||
"expected": {
|
||||
"value": 0.03
|
||||
},
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses negative zero as zero",
|
||||
"input": "value: -0",
|
||||
"expected": {
|
||||
"value": 0
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Negative zero decodes to 0; most host environments do not distinguish -0 from 0"
|
||||
},
|
||||
{
|
||||
"name": "parses negative zero with fractional part",
|
||||
"input": "value: -0.0",
|
||||
"expected": {
|
||||
"value": 0
|
||||
},
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses array with mixed numeric forms",
|
||||
"input": "nums[5]: 42,-1E+03,1.5000,-0,2.5e2",
|
||||
"expected": {
|
||||
"nums": [42, -1000, 1.5, 0, 250]
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Decoders normalize all numeric forms to host numeric values"
|
||||
},
|
||||
{
|
||||
"name": "treats leading zero as string not number",
|
||||
"input": "value: 05",
|
||||
"expected": {
|
||||
"value": "05"
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Forbidden leading zeros cause tokens to be treated as strings"
|
||||
},
|
||||
{
|
||||
"name": "parses very small exponent",
|
||||
"input": "value: 1e-10",
|
||||
"expected": {
|
||||
"value": 0.0000000001
|
||||
},
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses integer with positive exponent",
|
||||
"input": "value: 5E+00",
|
||||
"expected": {
|
||||
"value": 5
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Exponent +00 results in the integer 5"
|
||||
},
|
||||
{
|
||||
"name": "parses zero with exponent as number",
|
||||
"input": "value: 0e1",
|
||||
"expected": {
|
||||
"value": 0
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Exponent forms with a zero integer part (0e1) are valid numbers"
|
||||
},
|
||||
{
|
||||
"name": "parses negative zero with exponent as number",
|
||||
"input": "value: -0e1",
|
||||
"expected": {
|
||||
"value": 0
|
||||
},
|
||||
"specSection": "4",
|
||||
"note": "Negative zero with exponent (-0e1) decodes to numeric 0"
|
||||
},
|
||||
{
|
||||
"name": "parses exponent notation",
|
||||
"input": "1e6",
|
||||
"expected": 1000000,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses exponent notation with uppercase E",
|
||||
"input": "1E+6",
|
||||
"expected": 1000000,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses negative exponent notation",
|
||||
"input": "-1e-3",
|
||||
"expected": -0.001,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "treats unquoted leading-zero number as string",
|
||||
"input": "05",
|
||||
"expected": "05",
|
||||
"specSection": "4",
|
||||
"note": "Leading zeros make it a string"
|
||||
},
|
||||
{
|
||||
"name": "treats unquoted multi-leading-zero as string",
|
||||
"input": "007",
|
||||
"expected": "007",
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "treats unquoted octal-like as string",
|
||||
"input": "0123",
|
||||
"expected": "0123",
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "treats leading-zero in object value as string",
|
||||
"input": "a: 05",
|
||||
"expected": { "a": "05" },
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "treats leading-zeros in array as strings",
|
||||
"input": "nums[3]: 05,007,0123",
|
||||
"expected": { "nums": ["05", "007", "0123"] },
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "treats unquoted negative leading-zero number as string",
|
||||
"input": "-05",
|
||||
"expected": "-05",
|
||||
"specSection": "4",
|
||||
"note": "Negative numbers with leading zeros in the integer part are treated as strings"
|
||||
},
|
||||
{
|
||||
"name": "treats negative leading-zeros in array as strings",
|
||||
"input": "nums[2]: -05,-007",
|
||||
"expected": {
|
||||
"nums": ["-05", "-007"]
|
||||
},
|
||||
"specSection": "4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Object decoding - simple objects, nested objects, key parsing, quoted values",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses objects with primitive values",
|
||||
"input": "id: 123\nname: Ada\nactive: true",
|
||||
"expected": {
|
||||
"id": 123,
|
||||
"name": "Ada",
|
||||
"active": true
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses null values in objects",
|
||||
"input": "id: 123\nvalue: null",
|
||||
"expected": {
|
||||
"id": 123,
|
||||
"value": null
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses empty nested object header",
|
||||
"input": "user:",
|
||||
"expected": {
|
||||
"user": {}
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with colon",
|
||||
"input": "note: \"a:b\"",
|
||||
"expected": {
|
||||
"note": "a:b"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with comma",
|
||||
"input": "note: \"a,b\"",
|
||||
"expected": {
|
||||
"note": "a,b"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with newline escape",
|
||||
"input": "text: \"line1\\nline2\"",
|
||||
"expected": {
|
||||
"text": "line1\nline2"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with escaped quotes",
|
||||
"input": "text: \"say \\\"hello\\\"\"",
|
||||
"expected": {
|
||||
"text": "say \"hello\""
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with leading/trailing spaces",
|
||||
"input": "text: \" padded \"",
|
||||
"expected": {
|
||||
"text": " padded "
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted object value with only spaces",
|
||||
"input": "text: \" \"",
|
||||
"expected": {
|
||||
"text": " "
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string value that looks like true",
|
||||
"input": "v: \"true\"",
|
||||
"expected": {
|
||||
"v": "true"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string value that looks like integer",
|
||||
"input": "v: \"42\"",
|
||||
"expected": {
|
||||
"v": "42"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string value that looks like negative decimal",
|
||||
"input": "v: \"-7.5\"",
|
||||
"expected": {
|
||||
"v": "-7.5"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with colon",
|
||||
"input": "\"order:id\": 7",
|
||||
"expected": {
|
||||
"order:id": 7
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with brackets",
|
||||
"input": "\"[index]\": 5",
|
||||
"expected": {
|
||||
"[index]": 5
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "treats extra brackets after valid array segment as literal key",
|
||||
"input": "foo[1][bar]: 10",
|
||||
"expected": {
|
||||
"foo[1][bar]": 10
|
||||
},
|
||||
"specSection": "6",
|
||||
"note": "Non-whitespace [bar] between ] and : prevents array header interpretation"
|
||||
},
|
||||
{
|
||||
"name": "treats non-integer bracket content as literal key",
|
||||
"input": "foo[bar][1]: 20",
|
||||
"expected": {
|
||||
"foo[bar][1]": 20
|
||||
},
|
||||
"specSection": "6",
|
||||
"note": "[bar] fails integer parsing; line is not an array header"
|
||||
},
|
||||
{
|
||||
"name": "treats text between bracket segment and colon as literal key",
|
||||
"input": "foo[2]extra: a,b",
|
||||
"expected": {
|
||||
"foo[2]extra": "a,b"
|
||||
},
|
||||
"specSection": "6",
|
||||
"note": "Non-whitespace content between ] and : prevents array header interpretation"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with braces",
|
||||
"input": "\"{key}\": 5",
|
||||
"expected": {
|
||||
"{key}": 5
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with comma",
|
||||
"input": "\"a,b\": 1",
|
||||
"expected": {
|
||||
"a,b": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with spaces",
|
||||
"input": "\"full name\": Ada",
|
||||
"expected": {
|
||||
"full name": "Ada"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with leading hyphen",
|
||||
"input": "\"-lead\": 1",
|
||||
"expected": {
|
||||
"-lead": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted key with leading and trailing spaces",
|
||||
"input": "\" a \": 1",
|
||||
"expected": {
|
||||
" a ": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted numeric key",
|
||||
"input": "\"123\": x",
|
||||
"expected": {
|
||||
"123": "x"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted empty string key",
|
||||
"input": "\"\": 1",
|
||||
"expected": {
|
||||
"": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses dotted keys as identifiers",
|
||||
"input": "user.name: Ada",
|
||||
"expected": {
|
||||
"user.name": "Ada"
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses underscore-prefixed keys",
|
||||
"input": "_private: 1",
|
||||
"expected": {
|
||||
"_private": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses underscore-containing keys",
|
||||
"input": "user_name: 1",
|
||||
"expected": {
|
||||
"user_name": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "unescapes newline in key",
|
||||
"input": "\"line\\nbreak\": 1",
|
||||
"expected": {
|
||||
"line\nbreak": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "unescapes tab in key",
|
||||
"input": "\"tab\\there\": 2",
|
||||
"expected": {
|
||||
"tab\there": 2
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "unescapes quotes in key",
|
||||
"input": "\"he said \\\"hi\\\"\": 1",
|
||||
"expected": {
|
||||
"he said \"hi\"": 1
|
||||
},
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "parses deeply nested objects with indentation",
|
||||
"input": "a:\n b:\n c: deep",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": "deep"
|
||||
}
|
||||
}
|
||||
},
|
||||
"specSection": "8"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"version": "1.5",
|
||||
"category": "decode",
|
||||
"description": "Path expansion with safe mode, deep merge, conflict resolution tied to strict mode",
|
||||
"tests": [
|
||||
{
|
||||
"name": "expands dotted key to nested object in safe mode",
|
||||
"input": "a.b.c: 1",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "expands dotted key with inline array",
|
||||
"input": "data.meta.items[2]: a,b",
|
||||
"expected": {
|
||||
"data": {
|
||||
"meta": {
|
||||
"items": ["a", "b"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "expands dotted key with tabular array",
|
||||
"input": "a.b.items[2]{id,name}:\n 1,A\n 2,B",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "A" },
|
||||
{ "id": 2, "name": "B" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "preserves literal dotted keys when expansion is off",
|
||||
"input": "user.name: Ada",
|
||||
"expected": {
|
||||
"user.name": "Ada"
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "off"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "expands and deep-merges preserving document-order insertion",
|
||||
"input": "a.b.c: 1\na.b.d: 2\na.e: 3",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1,
|
||||
"d": 2
|
||||
},
|
||||
"e": 3
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "throws on expansion conflict (object vs primitive) when strict=true",
|
||||
"input": "a.b: 1\na: 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"expandPaths": "safe",
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.5"
|
||||
},
|
||||
{
|
||||
"name": "throws on expansion conflict (object vs array) when strict=true",
|
||||
"input": "a.b: 1\na[2]: 2,3",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"expandPaths": "safe",
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "14.5"
|
||||
},
|
||||
{
|
||||
"name": "applies LWW when strict=false (primitive overwrites expanded object)",
|
||||
"input": "a.b: 1\na: 2",
|
||||
"expected": {
|
||||
"a": 2
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe",
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "13.4",
|
||||
"note": "Document order determines winner: later key overwrites earlier"
|
||||
},
|
||||
{
|
||||
"name": "applies LWW when strict=false (expanded object overwrites primitive)",
|
||||
"input": "a: 1\na.b: 2",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": 2
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe",
|
||||
"strict": false
|
||||
},
|
||||
"specSection": "13.4",
|
||||
"note": "Document order determines winner: later key overwrites earlier"
|
||||
},
|
||||
{
|
||||
"name": "preserves quoted dotted key as literal when expandPaths=safe",
|
||||
"input": "a.b: 1\n\"c.d\": 2",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": 1
|
||||
},
|
||||
"c.d": 2
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "preserves non-IdentifierSegment keys as literals",
|
||||
"input": "full-name.x: 1",
|
||||
"expected": {
|
||||
"full-name.x": 1
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "expands keys creating empty nested objects",
|
||||
"input": "a.b.c:",
|
||||
"expected": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"expandPaths": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Primitive value decoding - strings, numbers, booleans, null, unescaping",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses safe unquoted string",
|
||||
"input": "hello",
|
||||
"expected": "hello",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses unquoted string with underscore and numbers",
|
||||
"input": "Ada_99",
|
||||
"expected": "Ada_99",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses empty quoted string",
|
||||
"input": "\"\"",
|
||||
"expected": "",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string with newline escape",
|
||||
"input": "\"line1\\nline2\"",
|
||||
"expected": "line1\nline2",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string with tab escape",
|
||||
"input": "\"tab\\there\"",
|
||||
"expected": "tab\there",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string with carriage return escape",
|
||||
"input": "\"return\\rcarriage\"",
|
||||
"expected": "return\rcarriage",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string with backslash escape",
|
||||
"input": "\"C:\\\\Users\\\\path\"",
|
||||
"expected": "C:\\Users\\path",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "parses quoted string with escaped quotes",
|
||||
"input": "\"say \\\"hello\\\"\"",
|
||||
"expected": "say \"hello\"",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "parses Unicode string",
|
||||
"input": "café",
|
||||
"expected": "café",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses Chinese characters",
|
||||
"input": "你好",
|
||||
"expected": "你好",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses emoji",
|
||||
"input": "🚀",
|
||||
"expected": "🚀",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses string with emoji and spaces",
|
||||
"input": "hello 👋 world",
|
||||
"expected": "hello 👋 world",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "parses positive integer",
|
||||
"input": "42",
|
||||
"expected": 42,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses decimal number",
|
||||
"input": "3.14",
|
||||
"expected": 3.14,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses negative integer",
|
||||
"input": "-7",
|
||||
"expected": -7,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses true",
|
||||
"input": "true",
|
||||
"expected": true,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses false",
|
||||
"input": "false",
|
||||
"expected": false,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "parses null",
|
||||
"input": "null",
|
||||
"expected": null,
|
||||
"specSection": "4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for true",
|
||||
"input": "\"true\"",
|
||||
"expected": "true",
|
||||
"specSection": "7.4",
|
||||
"note": "Quoted primitive remains string"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for false",
|
||||
"input": "\"false\"",
|
||||
"expected": "false",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for null",
|
||||
"input": "\"null\"",
|
||||
"expected": "null",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for integer",
|
||||
"input": "\"42\"",
|
||||
"expected": "42",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for negative decimal",
|
||||
"input": "\"-3.14\"",
|
||||
"expected": "-3.14",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for scientific notation",
|
||||
"input": "\"1e-6\"",
|
||||
"expected": "1e-6",
|
||||
"specSection": "7.4"
|
||||
},
|
||||
{
|
||||
"name": "respects ambiguity quoting for leading-zero",
|
||||
"input": "\"05\"",
|
||||
"expected": "05",
|
||||
"specSection": "7.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Root form detection - empty document, single primitive, multiple primitives",
|
||||
"tests": [
|
||||
{
|
||||
"name": "parses empty document as empty object",
|
||||
"input": "",
|
||||
"expected": {},
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "5",
|
||||
"note": "Empty input (no non-empty lines) decodes to empty object"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Validation errors - length mismatches, invalid escapes, syntax errors, delimiter mismatches",
|
||||
"tests": [
|
||||
{
|
||||
"name": "throws on array length mismatch (inline primitives - too many)",
|
||||
"input": "tags[2]: a,b,c",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.1"
|
||||
},
|
||||
{
|
||||
"name": "throws on array length mismatch (list format - too many)",
|
||||
"input": "items[1]:\n - 1\n - 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.1"
|
||||
},
|
||||
{
|
||||
"name": "throws on tabular row value count mismatch with header field count",
|
||||
"input": "items[2]{id,name}:\n 1,Ada\n 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.1"
|
||||
},
|
||||
{
|
||||
"name": "throws on tabular row count mismatch with header length",
|
||||
"input": "[1]{id}:\n 1\n 2",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.1"
|
||||
},
|
||||
{
|
||||
"name": "throws on invalid escape sequence",
|
||||
"input": "\"a\\x\"",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.2"
|
||||
},
|
||||
{
|
||||
"name": "throws on unterminated string",
|
||||
"input": "\"unterminated",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.2"
|
||||
},
|
||||
{
|
||||
"name": "throws on missing colon in key-value context",
|
||||
"input": "a:\n user",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.2"
|
||||
},
|
||||
{
|
||||
"name": "throws on two primitives at root depth in strict mode",
|
||||
"input": "hello\nworld",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "5"
|
||||
},
|
||||
{
|
||||
"name": "throws on delimiter mismatch (header declares tab, row uses comma)",
|
||||
"input": "items[2\t]{a\tb}:\n 1,2\n 3,4",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"specSection": "14.2"
|
||||
},
|
||||
{
|
||||
"name": "throws on mismatched delimiter between bracket and brace fields",
|
||||
"input": "items[2\t]{a,b}:\n 1\t2\n 3\t4",
|
||||
"expected": null,
|
||||
"shouldError": true,
|
||||
"options": {
|
||||
"strict": true
|
||||
},
|
||||
"specSection": "6"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "decode",
|
||||
"description": "Whitespace tolerance in decoding - surrounding spaces around delimiters and values",
|
||||
"tests": [
|
||||
{
|
||||
"name": "tolerates spaces around commas in inline arrays",
|
||||
"input": "tags[3]: a , b , c",
|
||||
"expected": {
|
||||
"tags": ["a", "b", "c"]
|
||||
},
|
||||
"specSection": "12",
|
||||
"note": "Surrounding whitespace SHOULD be tolerated; tokens are trimmed"
|
||||
},
|
||||
{
|
||||
"name": "tolerates spaces around pipes in inline arrays",
|
||||
"input": "tags[3|]: a | b | c",
|
||||
"expected": {
|
||||
"tags": ["a", "b", "c"]
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "tolerates spaces around tabs in inline arrays",
|
||||
"input": "tags[3\t]: a \t b \t c",
|
||||
"expected": {
|
||||
"tags": ["a", "b", "c"]
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "tolerates leading and trailing spaces in tabular row values",
|
||||
"input": "items[2]{id,name}:\n 1 , Alice \n 2 , Bob ",
|
||||
"expected": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "Alice" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
},
|
||||
"specSection": "12",
|
||||
"note": "Values in tabular rows are trimmed"
|
||||
},
|
||||
{
|
||||
"name": "tolerates spaces around delimiters with quoted values",
|
||||
"input": "items[3]: \"a\" , \"b\" , \"c\"",
|
||||
"expected": {
|
||||
"items": ["a", "b", "c"]
|
||||
},
|
||||
"specSection": "12"
|
||||
},
|
||||
{
|
||||
"name": "parses empty tokens as empty string",
|
||||
"input": "items[3]: a,,c",
|
||||
"expected": {
|
||||
"items": ["a", "", "c"]
|
||||
},
|
||||
"specSection": "12",
|
||||
"note": "Empty token (nothing between delimiters) decodes to empty string"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"version": "3.0",
|
||||
"category": "encode",
|
||||
"description": "Nested and mixed array encoding - arrays of arrays, mixed type arrays, root arrays",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes nested arrays of primitives",
|
||||
"input": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"expected": "pairs[2]:\n - [2]: a,b\n - [2]: c,d",
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings containing delimiters in nested arrays",
|
||||
"input": {
|
||||
"pairs": [["a", "b"], ["c,d", "e:f", "true"]]
|
||||
},
|
||||
"expected": "pairs[2]:\n - [2]: a,b\n - [3]: \"c,d\",\"e:f\",\"true\"",
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty inner arrays",
|
||||
"input": {
|
||||
"pairs": [[], []]
|
||||
},
|
||||
"expected": "pairs[2]:\n - [0]:\n - [0]:",
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes mixed-length inner arrays",
|
||||
"input": {
|
||||
"pairs": [[1], [2, 3]]
|
||||
},
|
||||
"expected": "pairs[2]:\n - [1]: 1\n - [2]: 2,3",
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level primitive array",
|
||||
"input": ["x", "y", "true", true, 10],
|
||||
"expected": "[5]: x,y,\"true\",true,10",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array of uniform objects in tabular format",
|
||||
"input": [{ "id": 1 }, { "id": 2 }],
|
||||
"expected": "[2]{id}:\n 1\n 2",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array of non-uniform objects in list format",
|
||||
"input": [{ "id": 1 }, { "id": 2, "name": "Ada" }],
|
||||
"expected": "[2]:\n - id: 1\n - id: 2\n name: Ada",
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array mixing primitive, object, and array of objects in list format",
|
||||
"input": ["summary", { "id": 1, "name": "Ada" }, [{ "id": 2 }, { "status": "draft" }]],
|
||||
"expected": "[3]:\n - summary\n - id: 1\n name: Ada\n - [2]:\n - id: 2\n - status: draft",
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level arrays of arrays",
|
||||
"input": [[1, 2], []],
|
||||
"expected": "[2]:\n - [2]: 1,2\n - [0]:",
|
||||
"specSection": "9.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty root-level array",
|
||||
"input": [],
|
||||
"expected": "[0]:",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes complex nested structure",
|
||||
"input": {
|
||||
"user": {
|
||||
"id": 123,
|
||||
"name": "Ada",
|
||||
"tags": ["reading", "gaming"],
|
||||
"active": true,
|
||||
"prefs": []
|
||||
}
|
||||
},
|
||||
"expected": "user:\n id: 123\n name: Ada\n tags[2]: reading,gaming\n active: true\n prefs[0]:",
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for arrays mixing primitives and objects",
|
||||
"input": {
|
||||
"items": [1, { "a": 1 }, "text"]
|
||||
},
|
||||
"expected": "items[3]:\n - 1\n - a: 1\n - text",
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for arrays mixing objects and arrays",
|
||||
"input": {
|
||||
"items": [{ "a": 1 }, [1, 2]]
|
||||
},
|
||||
"expected": "items[2]:\n - a: 1\n - [2]: 1,2",
|
||||
"specSection": "9.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"version": "3.0",
|
||||
"category": "encode",
|
||||
"description": "Arrays of objects encoding - list format for non-uniform objects and complex structures",
|
||||
"tests": [
|
||||
{
|
||||
"name": "uses list format for objects with different fields",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "First" },
|
||||
{ "id": 2, "name": "Second", "extra": true }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]:\n - id: 1\n name: First\n - id: 2\n name: Second\n extra: true",
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for objects with nested values",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "nested": { "x": 1 } }
|
||||
]
|
||||
},
|
||||
"expected": "items[1]:\n - id: 1\n nested:\n x: 1",
|
||||
"specSection": "9.4"
|
||||
},
|
||||
{
|
||||
"name": "preserves field order in list items - array first",
|
||||
"input": {
|
||||
"items": [{ "nums": [1, 2, 3], "name": "Ada" }]
|
||||
},
|
||||
"expected": "items[1]:\n - nums[3]: 1,2,3\n name: Ada",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "preserves field order in list items - primitive first",
|
||||
"input": {
|
||||
"items": [{ "name": "Ada", "nums": [1, 2, 3] }]
|
||||
},
|
||||
"expected": "items[1]:\n - name: Ada\n nums[3]: 1,2,3",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for objects containing arrays of arrays",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "matrix": [[1, 2], [3, 4]], "name": "grid" }
|
||||
]
|
||||
},
|
||||
"expected": "items[1]:\n - matrix[2]:\n - [2]: 1,2\n - [2]: 3,4\n name: grid",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "uses tabular format for nested uniform object arrays",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "users": [{ "id": 1, "name": "Ada" }, { "id": 2, "name": "Bob" }], "status": "active" }
|
||||
]
|
||||
},
|
||||
"expected": "items[1]:\n - users[2]{id,name}:\n 1,Ada\n 2,Bob\n status: active",
|
||||
"specSection": "10",
|
||||
"note": "YAML-style encoding for list-item objects with tabular array as first field"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for nested object arrays with mismatched keys",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "users": [{ "id": 1, "name": "Ada" }, { "id": 2 }], "status": "active" }
|
||||
]
|
||||
},
|
||||
"expected": "items[1]:\n - users[2]:\n - id: 1\n name: Ada\n - id: 2\n status: active",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for objects with multiple array fields",
|
||||
"input": {
|
||||
"items": [{ "nums": [1, 2], "tags": ["a", "b"], "name": "test" }]
|
||||
},
|
||||
"expected": "items[1]:\n - nums[2]: 1,2\n tags[2]: a,b\n name: test",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "uses list format for objects with only array fields",
|
||||
"input": {
|
||||
"items": [{ "nums": [1, 2, 3], "tags": ["a", "b"] }]
|
||||
},
|
||||
"expected": "items[1]:\n - nums[3]: 1,2,3\n tags[2]: a,b",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "encodes objects with empty arrays in list format",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "name": "Ada", "data": [] }
|
||||
]
|
||||
},
|
||||
"expected": "items[1]:\n - name: Ada\n data[0]:",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "uses canonical encoding for multi-field list-item objects with tabular arrays",
|
||||
"input": {
|
||||
"items": [{ "users": [{ "id": 1 }, { "id": 2 }], "note": "x" }]
|
||||
},
|
||||
"expected": "items[1]:\n - users[2]{id}:\n 1\n 2\n note: x",
|
||||
"specSection": "10",
|
||||
"note": "Tabular header on hyphen line with rows at depth +2 and sibling fields at depth +1"
|
||||
},
|
||||
{
|
||||
"name": "uses canonical encoding for single-field list-item tabular arrays",
|
||||
"input": {
|
||||
"items": [{ "users": [{ "id": 1, "name": "Ada" }, { "id": 2, "name": "Bob" }] }]
|
||||
},
|
||||
"expected": "items[1]:\n - users[2]{id,name}:\n 1,Ada\n 2,Bob",
|
||||
"specSection": "10",
|
||||
"note": "Tabular header on hyphen line with rows at depth +2"
|
||||
},
|
||||
{
|
||||
"name": "places empty arrays on hyphen line when first",
|
||||
"input": {
|
||||
"items": [{ "data": [], "name": "x" }]
|
||||
},
|
||||
"expected": "items[1]:\n - data[0]:\n name: x",
|
||||
"specSection": "10"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty object list items as bare hyphen",
|
||||
"input": {
|
||||
"items": ["first", "second", {}]
|
||||
},
|
||||
"expected": "items[3]:\n - first\n - second\n -",
|
||||
"specSection": "10",
|
||||
"note": "Empty object list items encode as a single \"-\" line at the list-item depth"
|
||||
},
|
||||
{
|
||||
"name": "uses field order from first object for tabular headers",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "a": 1, "b": 2, "c": 3 },
|
||||
{ "c": 30, "b": 20, "a": 10 }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{a,b,c}:\n 1,2,3\n 10,20,30",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "uses list format when one object has nested field",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "data": "string" },
|
||||
{ "id": 2, "data": { "nested": true } }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]:\n - id: 1\n data: string\n - id: 2\n data:\n nested: true",
|
||||
"specSection": "9.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Primitive array encoding - inline arrays of strings, numbers, booleans",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes string arrays inline",
|
||||
"input": {
|
||||
"tags": ["reading", "gaming"]
|
||||
},
|
||||
"expected": "tags[2]: reading,gaming",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes number arrays inline",
|
||||
"input": {
|
||||
"nums": [1, 2, 3]
|
||||
},
|
||||
"expected": "nums[3]: 1,2,3",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes mixed primitive arrays inline",
|
||||
"input": {
|
||||
"data": ["x", "y", true, 10]
|
||||
},
|
||||
"expected": "data[4]: x,y,true,10",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty arrays",
|
||||
"input": {
|
||||
"items": []
|
||||
},
|
||||
"expected": "items[0]:",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty string keys for inline arrays",
|
||||
"input": {
|
||||
"": [1, 2, 3]
|
||||
},
|
||||
"expected": "\"\"[3]: 1,2,3",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty string keys for empty arrays",
|
||||
"input": {
|
||||
"": []
|
||||
},
|
||||
"expected": "\"\"[0]:",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty string in single-item array",
|
||||
"input": {
|
||||
"items": [""]
|
||||
},
|
||||
"expected": "items[1]: \"\"",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty string in multi-item array",
|
||||
"input": {
|
||||
"items": ["a", "", "b"]
|
||||
},
|
||||
"expected": "items[3]: a,\"\",b",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes whitespace-only strings in arrays",
|
||||
"input": {
|
||||
"items": [" ", " "]
|
||||
},
|
||||
"expected": "items[2]: \" \",\" \"",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "quotes array strings with comma",
|
||||
"input": {
|
||||
"items": ["a", "b,c", "d:e"]
|
||||
},
|
||||
"expected": "items[3]: a,\"b,c\",\"d:e\"",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings that look like booleans in arrays",
|
||||
"input": {
|
||||
"items": ["x", "true", "42", "-3.14"]
|
||||
},
|
||||
"expected": "items[4]: x,\"true\",\"42\",\"-3.14\"",
|
||||
"specSection": "9.1"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings with structural meanings in arrays",
|
||||
"input": {
|
||||
"items": ["[5]", "- item", "{key}"]
|
||||
},
|
||||
"expected": "items[3]: \"[5]\",\"- item\",\"{key}\"",
|
||||
"specSection": "9.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Tabular array encoding - arrays of uniform objects with primitive values",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes arrays of uniform objects in tabular format",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{sku,qty,price}:\n A1,2,9.99\n B2,1,14.5",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "encodes null values in tabular format",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "value": null },
|
||||
{ "id": 2, "value": "test" }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{id,value}:\n 1,null\n 2,test",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings containing delimiters in tabular rows",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "sku": "A,1", "desc": "cool", "qty": 2 },
|
||||
{ "sku": "B2", "desc": "wip: test", "qty": 1 }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{sku,desc,qty}:\n \"A,1\",cool,2\n B2,\"wip: test\",1",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes ambiguous strings in tabular rows",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "status": "true" },
|
||||
{ "id": 2, "status": "false" }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{id,status}:\n 1,\"true\"\n 2,\"false\"",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "encodes tabular arrays with keys needing quotes",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "order:id": 1, "full name": "Ada" },
|
||||
{ "order:id": 2, "full name": "Bob" }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{\"order:id\",\"full name\"}:\n 1,Ada\n 2,Bob",
|
||||
"specSection": "9.3"
|
||||
},
|
||||
{
|
||||
"name": "encodes tabular arrays with empty string keys",
|
||||
"input": {
|
||||
"": [
|
||||
{ "id": 1, "name": "Ada" },
|
||||
{ "id": 2, "name": "Bob" }
|
||||
]
|
||||
},
|
||||
"expected": "\"\"[2]{id,name}:\n 1,Ada\n 2,Bob",
|
||||
"specSection": "9.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Delimiter options - tab and pipe delimiters, delimiter-aware quoting",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes primitive arrays with tab delimiter",
|
||||
"input": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"expected": "tags[3\t]: reading\tgaming\tcoding",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes primitive arrays with pipe delimiter",
|
||||
"input": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"expected": "tags[3|]: reading|gaming|coding",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes primitive arrays with comma delimiter",
|
||||
"input": {
|
||||
"tags": ["reading", "gaming", "coding"]
|
||||
},
|
||||
"expected": "tags[3]: reading,gaming,coding",
|
||||
"options": {
|
||||
"delimiter": ","
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes tabular arrays with tab delimiter",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"expected": "items[2\t]{sku\tqty\tprice}:\n A1\t2\t9.99\n B2\t1\t14.5",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes tabular arrays with pipe delimiter",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "sku": "A1", "qty": 2, "price": 9.99 },
|
||||
{ "sku": "B2", "qty": 1, "price": 14.5 }
|
||||
]
|
||||
},
|
||||
"expected": "items[2|]{sku|qty|price}:\n A1|2|9.99\n B2|1|14.5",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes nested arrays with tab delimiter",
|
||||
"input": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"expected": "pairs[2\t]:\n - [2\t]: a\tb\n - [2\t]: c\td",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes nested arrays with pipe delimiter",
|
||||
"input": {
|
||||
"pairs": [["a", "b"], ["c", "d"]]
|
||||
},
|
||||
"expected": "pairs[2|]:\n - [2|]: a|b\n - [2|]: c|d",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array with tab delimiter",
|
||||
"input": ["x", "y", "z"],
|
||||
"expected": "[3\t]: x\ty\tz",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array with pipe delimiter",
|
||||
"input": ["x", "y", "z"],
|
||||
"expected": "[3|]: x|y|z",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array of objects with tab delimiter",
|
||||
"input": [{ "id": 1 }, { "id": 2 }],
|
||||
"expected": "[2\t]{id}:\n 1\n 2",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "encodes root-level array of objects with pipe delimiter",
|
||||
"input": [{ "id": 1 }, { "id": 2 }],
|
||||
"expected": "[2|]{id}:\n 1\n 2",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings containing tab delimiter",
|
||||
"input": {
|
||||
"items": ["a", "b\tc", "d"]
|
||||
},
|
||||
"expected": "items[3\t]: a\t\"b\\tc\"\td",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "quotes strings containing pipe delimiter",
|
||||
"input": {
|
||||
"items": ["a", "b|c", "d"]
|
||||
},
|
||||
"expected": "items[3|]: a|\"b|c\"|d",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not quote commas with tab delimiter",
|
||||
"input": {
|
||||
"items": ["a,b", "c,d"]
|
||||
},
|
||||
"expected": "items[2\t]: a,b\tc,d",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not quote commas with pipe delimiter",
|
||||
"input": {
|
||||
"items": ["a,b", "c,d"]
|
||||
},
|
||||
"expected": "items[2|]: a,b|c,d",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "quotes tabular values containing comma delimiter",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "note": "a,b" },
|
||||
{ "id": 2, "note": "c,d" }
|
||||
]
|
||||
},
|
||||
"expected": "items[2]{id,note}:\n 1,\"a,b\"\n 2,\"c,d\"",
|
||||
"options": {
|
||||
"delimiter": ","
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not quote commas in tabular values with tab delimiter",
|
||||
"input": {
|
||||
"items": [
|
||||
{ "id": 1, "note": "a,b" },
|
||||
{ "id": 2, "note": "c,d" }
|
||||
]
|
||||
},
|
||||
"expected": "items[2\t]{id\tnote}:\n 1\ta,b\n 2\tc,d",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not quote commas in object values with pipe delimiter",
|
||||
"input": {
|
||||
"note": "a,b"
|
||||
},
|
||||
"expected": "note: a,b",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "does not quote commas in object values with tab delimiter",
|
||||
"input": {
|
||||
"note": "a,b"
|
||||
},
|
||||
"expected": "note: a,b",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "quotes nested array values containing pipe delimiter",
|
||||
"input": {
|
||||
"pairs": [["a", "b|c"]]
|
||||
},
|
||||
"expected": "pairs[1|]:\n - [2|]: a|\"b|c\"",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "quotes nested array values containing tab delimiter",
|
||||
"input": {
|
||||
"pairs": [["a", "b\tc"]]
|
||||
},
|
||||
"expected": "pairs[1\t]:\n - [2\t]: a\t\"b\\tc\"",
|
||||
"options": {
|
||||
"delimiter": "\t"
|
||||
},
|
||||
"specSection": "11"
|
||||
},
|
||||
{
|
||||
"name": "preserves ambiguity quoting regardless of delimiter",
|
||||
"input": {
|
||||
"items": ["true", "42", "-3.14"]
|
||||
},
|
||||
"expected": "items[3|]: \"true\"|\"42\"|\"-3.14\"",
|
||||
"options": {
|
||||
"delimiter": "|"
|
||||
},
|
||||
"specSection": "11"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"version": "1.5",
|
||||
"category": "encode",
|
||||
"description": "Key folding with safe mode, depth control, collision avoidance",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes folded chain to primitive (safe mode)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a.b.c: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes folded chain with inline array",
|
||||
"input": {
|
||||
"data": {
|
||||
"meta": {
|
||||
"items": ["x", "y"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "data.meta.items[2]: x,y",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes folded chain with tabular array",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"items": [
|
||||
{ "id": 1, "name": "A" },
|
||||
{ "id": 2, "name": "B" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a.b.items[2]{id,name}:\n 1,A\n 2,B",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "skips folding when segment requires quotes (safe mode)",
|
||||
"input": {
|
||||
"data": {
|
||||
"full-name": {
|
||||
"x": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "data:\n \"full-name\":\n x: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "skips folding on sibling literal-key collision (safe mode)",
|
||||
"input": {
|
||||
"data": {
|
||||
"meta": {
|
||||
"items": [1, 2]
|
||||
}
|
||||
},
|
||||
"data.meta.items": "literal"
|
||||
},
|
||||
"expected": "data:\n meta:\n items[2]: 1,2\ndata.meta.items: literal",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4",
|
||||
"note": "Collision avoidance: folding would create duplicate key"
|
||||
},
|
||||
{
|
||||
"name": "encodes partial folding with flattenDepth=2",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": {
|
||||
"d": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a.b:\n c:\n d: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe",
|
||||
"flattenDepth": 2
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes full chain with flattenDepth=Infinity (default)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": {
|
||||
"d": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a.b.c.d: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes standard nesting with flattenDepth=0 (no folding)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a:\n b:\n c: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe",
|
||||
"flattenDepth": 0
|
||||
},
|
||||
"specSection": "13.4",
|
||||
"note": "flattenDepth=0 disables all folding"
|
||||
},
|
||||
{
|
||||
"name": "encodes standard nesting with flattenDepth=1 (no practical effect)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a:\n b:\n c: 1",
|
||||
"options": {
|
||||
"keyFolding": "safe",
|
||||
"flattenDepth": 1
|
||||
},
|
||||
"specSection": "13.4",
|
||||
"note": "flattenDepth=1 has no practical folding effect (requires at least 2 segments)"
|
||||
},
|
||||
{
|
||||
"name": "encodes standard nesting with keyFolding=off (baseline)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a:\n b:\n c: 1",
|
||||
"options": {
|
||||
"keyFolding": "off"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes folded chain ending with empty object",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a.b.c:",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "stops folding at array boundary (not single-key object)",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": [1, 2]
|
||||
}
|
||||
},
|
||||
"expected": "a.b[2]: 1,2",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
},
|
||||
{
|
||||
"name": "encodes folded chains preserving sibling field order",
|
||||
"input": {
|
||||
"first": {
|
||||
"second": {
|
||||
"third": 1
|
||||
}
|
||||
},
|
||||
"simple": 2,
|
||||
"short": {
|
||||
"path": 3
|
||||
}
|
||||
},
|
||||
"expected": "first.second.third: 1\nsimple: 2\nshort.path: 3",
|
||||
"options": {
|
||||
"keyFolding": "safe"
|
||||
},
|
||||
"specSection": "13.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Object encoding - simple objects, nested objects, key encoding",
|
||||
"tests": [
|
||||
{
|
||||
"name": "preserves key order in objects",
|
||||
"input": {
|
||||
"id": 123,
|
||||
"name": "Ada",
|
||||
"active": true
|
||||
},
|
||||
"expected": "id: 123\nname: Ada\nactive: true",
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "encodes null values in objects",
|
||||
"input": {
|
||||
"id": 123,
|
||||
"value": null
|
||||
},
|
||||
"expected": "id: 123\nvalue: null",
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty objects as empty string",
|
||||
"input": {},
|
||||
"expected": "",
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with colon",
|
||||
"input": {
|
||||
"note": "a:b"
|
||||
},
|
||||
"expected": "note: \"a:b\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with comma",
|
||||
"input": {
|
||||
"note": "a,b"
|
||||
},
|
||||
"expected": "note: \"a,b\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with newline",
|
||||
"input": {
|
||||
"text": "line1\nline2"
|
||||
},
|
||||
"expected": "text: \"line1\\nline2\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with embedded quotes",
|
||||
"input": {
|
||||
"text": "say \"hello\""
|
||||
},
|
||||
"expected": "text: \"say \\\"hello\\\"\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with leading space",
|
||||
"input": {
|
||||
"text": " padded "
|
||||
},
|
||||
"expected": "text: \" padded \"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value with only spaces",
|
||||
"input": {
|
||||
"text": " "
|
||||
},
|
||||
"expected": "text: \" \"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value that looks like true",
|
||||
"input": {
|
||||
"v": "true"
|
||||
},
|
||||
"expected": "v: \"true\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value that looks like number",
|
||||
"input": {
|
||||
"v": "42"
|
||||
},
|
||||
"expected": "v: \"42\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string value that looks like negative decimal",
|
||||
"input": {
|
||||
"v": "-7.5"
|
||||
},
|
||||
"expected": "v: \"-7.5\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with colon",
|
||||
"input": {
|
||||
"order:id": 7
|
||||
},
|
||||
"expected": "\"order:id\": 7",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with brackets",
|
||||
"input": {
|
||||
"[index]": 5
|
||||
},
|
||||
"expected": "\"[index]\": 5",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with braces",
|
||||
"input": {
|
||||
"{key}": 5
|
||||
},
|
||||
"expected": "\"{key}\": 5",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with comma",
|
||||
"input": {
|
||||
"a,b": 1
|
||||
},
|
||||
"expected": "\"a,b\": 1",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with spaces",
|
||||
"input": {
|
||||
"full name": "Ada"
|
||||
},
|
||||
"expected": "\"full name\": Ada",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with leading hyphen",
|
||||
"input": {
|
||||
"-lead": 1
|
||||
},
|
||||
"expected": "\"-lead\": 1",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes key with leading and trailing spaces",
|
||||
"input": {
|
||||
" a ": 1
|
||||
},
|
||||
"expected": "\" a \": 1",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes numeric key",
|
||||
"input": {
|
||||
"123": "x"
|
||||
},
|
||||
"expected": "\"123\": x",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "quotes empty string key",
|
||||
"input": {
|
||||
"": 1
|
||||
},
|
||||
"expected": "\"\": 1",
|
||||
"specSection": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "escapes newline in key",
|
||||
"input": {
|
||||
"line\nbreak": 1
|
||||
},
|
||||
"expected": "\"line\\nbreak\": 1",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "escapes tab in key",
|
||||
"input": {
|
||||
"tab\there": 2
|
||||
},
|
||||
"expected": "\"tab\\there\": 2",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "escapes quotes in key",
|
||||
"input": {
|
||||
"he said \"hi\"": 1
|
||||
},
|
||||
"expected": "\"he said \\\"hi\\\"\": 1",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "encodes deeply nested objects",
|
||||
"input": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": "deep"
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": "a:\n b:\n c: deep",
|
||||
"specSection": "8"
|
||||
},
|
||||
{
|
||||
"name": "encodes empty nested object",
|
||||
"input": {
|
||||
"user": {}
|
||||
},
|
||||
"expected": "user:",
|
||||
"specSection": "8"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Primitive value encoding - strings, numbers, booleans, null",
|
||||
"tests": [
|
||||
{
|
||||
"name": "encodes safe strings without quotes",
|
||||
"input": "hello",
|
||||
"expected": "hello",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes safe string with underscore and numbers",
|
||||
"input": "Ada_99",
|
||||
"expected": "Ada_99",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes empty string",
|
||||
"input": "",
|
||||
"expected": "\"\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like true",
|
||||
"input": "true",
|
||||
"expected": "\"true\"",
|
||||
"specSection": "7.2",
|
||||
"note": "String representation of boolean must be quoted"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like false",
|
||||
"input": "false",
|
||||
"expected": "\"false\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like null",
|
||||
"input": "null",
|
||||
"expected": "\"null\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like integer",
|
||||
"input": "42",
|
||||
"expected": "\"42\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like negative decimal",
|
||||
"input": "-3.14",
|
||||
"expected": "\"-3.14\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string that looks like scientific notation",
|
||||
"input": "1e-6",
|
||||
"expected": "\"1e-6\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string with leading zero",
|
||||
"input": "05",
|
||||
"expected": "\"05\"",
|
||||
"specSection": "7.2",
|
||||
"note": "Leading zeros make it non-numeric"
|
||||
},
|
||||
{
|
||||
"name": "escapes newline in string",
|
||||
"input": "line1\nline2",
|
||||
"expected": "\"line1\\nline2\"",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "escapes tab in string",
|
||||
"input": "tab\there",
|
||||
"expected": "\"tab\\there\"",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "escapes carriage return in string",
|
||||
"input": "return\rcarriage",
|
||||
"expected": "\"return\\rcarriage\"",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "escapes backslash in string",
|
||||
"input": "C:\\Users\\path",
|
||||
"expected": "\"C:\\\\Users\\\\path\"",
|
||||
"specSection": "7.1"
|
||||
},
|
||||
{
|
||||
"name": "quotes string with array-like syntax",
|
||||
"input": "[3]: x,y",
|
||||
"expected": "\"[3]: x,y\"",
|
||||
"specSection": "7.2",
|
||||
"note": "Looks like array header"
|
||||
},
|
||||
{
|
||||
"name": "quotes string starting with hyphen-space",
|
||||
"input": "- item",
|
||||
"expected": "\"- item\"",
|
||||
"specSection": "7.2",
|
||||
"note": "Looks like list item marker"
|
||||
},
|
||||
{
|
||||
"name": "quotes single hyphen as object value",
|
||||
"input": { "marker": "-" },
|
||||
"expected": "marker: \"-\"",
|
||||
"specSection": "7.2",
|
||||
"note": "Single hyphen must be quoted to avoid list item ambiguity"
|
||||
},
|
||||
{
|
||||
"name": "quotes string starting with hyphen as object value",
|
||||
"input": { "note": "- item" },
|
||||
"expected": "note: \"- item\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes single hyphen in array",
|
||||
"input": { "items": ["-"] },
|
||||
"expected": "items[1]: \"-\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes leading-hyphen string in array",
|
||||
"input": { "tags": ["a", "- item", "b"] },
|
||||
"expected": "tags[3]: a,\"- item\",b",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string with bracket notation",
|
||||
"input": "[test]",
|
||||
"expected": "\"[test]\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "quotes string with brace notation",
|
||||
"input": "{key}",
|
||||
"expected": "\"{key}\"",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes Unicode string without quotes",
|
||||
"input": "café",
|
||||
"expected": "café",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes Chinese characters without quotes",
|
||||
"input": "你好",
|
||||
"expected": "你好",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes emoji without quotes",
|
||||
"input": "🚀",
|
||||
"expected": "🚀",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes string with emoji and spaces",
|
||||
"input": "hello 👋 world",
|
||||
"expected": "hello 👋 world",
|
||||
"specSection": "7.2"
|
||||
},
|
||||
{
|
||||
"name": "encodes positive integer",
|
||||
"input": 42,
|
||||
"expected": "42",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes decimal number",
|
||||
"input": 3.14,
|
||||
"expected": "3.14",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes negative integer",
|
||||
"input": -7,
|
||||
"expected": "-7",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes zero",
|
||||
"input": 0,
|
||||
"expected": "0",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes negative zero as zero",
|
||||
"input": -0,
|
||||
"expected": "0",
|
||||
"specSection": "2",
|
||||
"note": "Negative zero normalizes to zero"
|
||||
},
|
||||
{
|
||||
"name": "encodes scientific notation as decimal",
|
||||
"input": 1000000,
|
||||
"expected": "1000000",
|
||||
"specSection": "2",
|
||||
"note": "1e6 input, but represented as decimal"
|
||||
},
|
||||
{
|
||||
"name": "encodes small decimal from scientific notation",
|
||||
"input": 0.000001,
|
||||
"expected": "0.000001",
|
||||
"specSection": "2",
|
||||
"note": "1e-6 input"
|
||||
},
|
||||
{
|
||||
"name": "encodes large number",
|
||||
"input": 100000000000000000000,
|
||||
"expected": "100000000000000000000",
|
||||
"specSection": "2",
|
||||
"note": "1e20"
|
||||
},
|
||||
{
|
||||
"name": "encodes MAX_SAFE_INTEGER",
|
||||
"input": 9007199254740991,
|
||||
"expected": "9007199254740991",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes repeating decimal with full precision",
|
||||
"input": 0.3333333333333333,
|
||||
"expected": "0.3333333333333333",
|
||||
"specSection": "2",
|
||||
"note": "Result of 1/3 in JavaScript"
|
||||
},
|
||||
{
|
||||
"name": "encodes true",
|
||||
"input": true,
|
||||
"expected": "true",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes false",
|
||||
"input": false,
|
||||
"expected": "false",
|
||||
"specSection": "2"
|
||||
},
|
||||
{
|
||||
"name": "encodes null",
|
||||
"input": null,
|
||||
"expected": "null",
|
||||
"specSection": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"version": "1.4",
|
||||
"category": "encode",
|
||||
"description": "Whitespace and formatting invariants - no trailing spaces, no trailing newlines",
|
||||
"tests": [
|
||||
{
|
||||
"name": "produces no trailing newline at end of output",
|
||||
"input": {
|
||||
"id": 123
|
||||
},
|
||||
"expected": "id: 123",
|
||||
"specSection": "12",
|
||||
"note": "Output should not end with newline character"
|
||||
},
|
||||
{
|
||||
"name": "maintains proper indentation for nested structures",
|
||||
"input": {
|
||||
"user": {
|
||||
"id": 123,
|
||||
"name": "Ada"
|
||||
},
|
||||
"items": ["a", "b"]
|
||||
},
|
||||
"expected": "user:\n id: 123\n name: Ada\nitems[2]: a,b",
|
||||
"specSection": "12",
|
||||
"note": "2-space indentation, no trailing spaces on any line"
|
||||
},
|
||||
{
|
||||
"name": "respects custom indent size option",
|
||||
"input": {
|
||||
"user": {
|
||||
"name": "Ada",
|
||||
"role": "admin"
|
||||
}
|
||||
},
|
||||
"expected": "user:\n name: Ada\n role: admin",
|
||||
"specSection": "12",
|
||||
"options": {
|
||||
"indent": 4
|
||||
},
|
||||
"note": "4-space indentation for nested objects when indent option is set to 4"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user