This is an automated email from the ASF dual-hosted git repository.

laskoviymishka pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-verification.git


The following commit(s) were added to refs/heads/main by this push:
     new 12b0509  Add formatting for fixtures (#15)
12b0509 is described below

commit 12b050929377853252123e345fa0659452da4a73
Author: Alex Stephen <[email protected]>
AuthorDate: Mon Oct 12 12:42:02 2026 -0700

    Add formatting for fixtures (#15)
    
    - selftest (renamed from test): add a positive control and require a
      FAILED report with exit 1, so a crashing validator no longer counts
      as a rejection
    - Prettier: set objectWrap to collapse so layout is a function of
      content, and reformat the schema fixtures to match
    - Scope formatting to table-spec/**/cases.json
    - Use npx --no-install so a missing install fails instead of fetching
      an unpinned Prettier
    - Declare the Node floor in package.json engines
    - Cache pip in the validate-fixtures workflow
    - Reorder the pre-PR steps in CONTRIBUTING
    
    ---------
    
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .github/workflows/license_check.yml     |   3 +-
 .github/workflows/validate-fixtures.yml |  37 +--
 .gitignore                              |   4 +
 .prettierrc.json                        |   4 +
 CONTRIBUTING.md                         |   6 +
 Makefile                                |  95 +++++++
 dev/.rat-excludes                       |   2 +
 package-lock.json                       |  32 +++
 package.json                            |  10 +
 table-spec/schema/core/cases.json       | 490 ++++++--------------------------
 table-spec/schema/unknown/cases.json    |  28 +-
 table-spec/types/geospatial/cases.json  |  24 +-
 table-spec/types/nested/cases.json      |  94 ++++--
 table-spec/types/primitive/cases.json   | 281 ++++++++++++++++--
 table-spec/types/variant/cases.json     |  18 +-
 15 files changed, 613 insertions(+), 515 deletions(-)

diff --git a/.github/workflows/license_check.yml 
b/.github/workflows/license_check.yml
index ee54cb4..06aa741 100644
--- a/.github/workflows/license_check.yml
+++ b/.github/workflows/license_check.yml
@@ -37,5 +37,4 @@ jobs:
     - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
       with:
         persist-credentials: false
-    - run: |
-        dev/check-license
+    - run: make license
diff --git a/.github/workflows/validate-fixtures.yml 
b/.github/workflows/validate-fixtures.yml
index cc78359..05e0eb3 100644
--- a/.github/workflows/validate-fixtures.yml
+++ b/.github/workflows/validate-fixtures.yml
@@ -42,29 +42,16 @@ jobs:
       uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # 
v6.3.0
       with:
         python-version: '3.12'
-    - name: Install validator deps
-      run: python3 -m pip install -r dev/requirements.txt
+        cache: pip
+        cache-dependency-path: dev/requirements.txt
+    - name: Install Node
+      uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # 
v7.0.0
+      with:
+        node-version: '22'
+        cache: npm
+    - name: Check fixture formatting
+      run: make lint
     - name: Validate cases.json
-      run: python3 dev/validate-fixtures.py
-    - name: Validator rejects malformed fixtures (self-test)
-      run: |
-        set -e
-        assert_reject() {  # <desc> <cases-json>
-          d="$(mktemp -d)"
-          mkdir -p "$d/table-spec/types/x"
-          printf '%s' "$2" > "$d/table-spec/types/x/cases.json"
-          test -f "$d/table-spec/types/x/cases.json"
-          if python3 dev/validate-fixtures.py "$d" >/dev/null 2>&1; then
-            echo "self-test FAILED: validator accepted a malformed fixture 
($1)"; exit 1
-          fi
-          echo "self-test ok: rejected ($1)"
-          rm -rf "$d"
-        }
-        assert_reject "valid:true with no decoded" 
'{"cases":[{"id":"a","valid":true,"input":"int","clause":"c","spec_ref":"s"}]}'
-        assert_reject "valid:false carrying decoded" 
'{"cases":[{"id":"a","valid":false,"input":"bad","decoded":{"type":"int"},"clause":"c","spec_ref":"s"}]}'
-        assert_reject "unknown property" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int"},"clause":"c","spec_ref":"s","spec-ref":"typo"}]}'
-        assert_reject "duplicate id in a surface" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int"},"clause":"c","spec_ref":"s"},{"id":"a","valid":true,"input":"long","decoded":{"type":"long"},"clause":"c","spec_ref":"s"}]}'
-        assert_reject "decoded decimal typo (precison)" 
'{"cases":[{"id":"a","valid":true,"input":"decimal(9,2)","decoded":{"type":"decimal","precison":9,"scale":2},"clause":"c","spec_ref":"s"}]}'
-        assert_reject "decoded fixed carrying len not length" 
'{"cases":[{"id":"a","valid":true,"input":"fixed[16]","decoded":{"type":"fixed","len":16},"clause":"c","spec_ref":"s"}]}'
-        assert_reject "decoded unknown type name" 
'{"cases":[{"id":"a","valid":true,"input":"x","decoded":{"type":"notatype"},"clause":"c","spec_ref":"s"}]}'
-        assert_reject "decoded simple type with extra key" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int","precision":9},"clause":"c","spec_ref":"s"}]}'
+      run: make validate
+    - name: Validator self-test
+      run: make selftest
diff --git a/.gitignore b/.gitignore
index b8ac23d..4d44edb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,7 @@
 # Python
 __pycache__/
 *.py[cod]
+.venv/
+
+# Node
+node_modules/
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..57b29d1
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,4 @@
+{
+  "printWidth": 120,
+  "objectWrap": "collapse"
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1caddc..3aec1db 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -268,6 +268,12 @@ to you, but it has to cover:
   It has to settle the comparison rule and how a failure is labeled. Pseudocode
   is one way to do that and prose is another.
 
+## Before opening a pull request
+
+Run `make install` once to install the tooling, then `make format` to format 
the
+fixtures with Prettier. CI runs `make lint` and rejects any `cases.json` that 
is
+not formatted. `make check` runs every check CI does.
+
 ## License headers
 
 Please do not add license headers to fixture files. They are test data, and a
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7c2ce35
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,95 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SHELL := bash
+PYTHON ?= python3
+PRETTIER := npx --no-install prettier
+FIXTURES := "table-spec/**/cases.json"
+VENV := .venv
+VENV_PYTHON := $(VENV)/bin/python
+VENV_STAMP := $(VENV)/.installed
+NODE_STAMP := node_modules/.installed
+
+.PHONY: help install format lint validate selftest license check clean
+
+help: ## Show available targets
+       @grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = 
":.*## "}; {printf "  %-10s %s\n", $$1, $$2}'
+
+$(VENV_STAMP): dev/requirements.txt
+       $(PYTHON) -m venv $(VENV)
+       $(VENV_PYTHON) -m pip install --quiet -r dev/requirements.txt
+       @touch $(VENV_STAMP)
+
+$(NODE_STAMP): package.json package-lock.json
+       npm ci --no-audit --no-fund
+       @touch $(NODE_STAMP)
+
+install: $(VENV_STAMP) $(NODE_STAMP) ## Install the Python and Node tooling 
dependencies
+
+format: $(NODE_STAMP) ## Format the JSON fixtures in place
+       $(PRETTIER) --log-level warn --write $(FIXTURES)
+
+lint: $(NODE_STAMP) ## Fail if any JSON fixture is not formatted
+       $(PRETTIER) --check $(FIXTURES)
+
+validate: $(VENV_STAMP) ## Validate every cases.json against the JSON Schemas
+       $(VENV_PYTHON) dev/validate-fixtures.py
+
+# Each fixture is written into a scratch table-spec tree. The well-formed one 
must
+# be accepted, so a validator that cannot run at all fails here; every 
malformed
+# one must be rejected by the validator itself (exit 1 and a FAILED report), 
not
+# by a crash.
+selftest: $(VENV_STAMP) ## Check the validator accepts a good fixture and 
rejects malformed ones
+       @set -e; \
+       run_validator() { \
+         d="$$(mktemp -d)"; \
+         mkdir -p "$$d/table-spec/types/x"; \
+         printf '%s' "$$1" > "$$d/table-spec/types/x/cases.json"; \
+         rc=0; out="$$($(VENV_PYTHON) dev/validate-fixtures.py "$$d" 2>&1)" || 
rc=$$?; \
+         rm -rf "$$d"; \
+       }; \
+       assert_accept() { \
+         run_validator "$$2"; \
+         if [ "$$rc" -ne 0 ]; then \
+           echo "FAILED: validator rejected a well-formed fixture ($$1)"; echo 
"$$out"; exit 1; \
+         fi; \
+         echo "ok: accepted ($$1)"; \
+       }; \
+       assert_reject() { \
+         run_validator "$$2"; \
+         if [ "$$rc" -ne 1 ] || ! grep -q '^FAILED: ' <<< "$$out"; then \
+           echo "FAILED: validator did not reject a malformed fixture ($$1), 
exit code $$rc"; echo "$$out"; exit 1; \
+         fi; \
+         echo "ok: rejected ($$1)"; \
+       }; \
+       assert_accept "well-formed case" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int"},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "valid:true with no decoded" 
'{"cases":[{"id":"a","valid":true,"input":"int","clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "valid:false carrying decoded" 
'{"cases":[{"id":"a","valid":false,"input":"bad","decoded":{"type":"int"},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "unknown property" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int"},"clause":"c","spec_ref":"s","spec-ref":"typo"}]}';
 \
+       assert_reject "duplicate id in a surface" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int"},"clause":"c","spec_ref":"s"},{"id":"a","valid":true,"input":"long","decoded":{"type":"long"},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "decoded decimal typo (precison)" 
'{"cases":[{"id":"a","valid":true,"input":"decimal(9,2)","decoded":{"type":"decimal","precison":9,"scale":2},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "decoded fixed carrying len not length" 
'{"cases":[{"id":"a","valid":true,"input":"fixed[16]","decoded":{"type":"fixed","len":16},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "decoded unknown type name" 
'{"cases":[{"id":"a","valid":true,"input":"x","decoded":{"type":"notatype"},"clause":"c","spec_ref":"s"}]}';
 \
+       assert_reject "decoded simple type with extra key" 
'{"cases":[{"id":"a","valid":true,"input":"int","decoded":{"type":"int","precision":9},"clause":"c","spec_ref":"s"}]}'
+
+license: ## Check ASF license headers with Apache RAT
+       dev/check-license
+
+check: lint validate selftest license ## Run all checks
+
+clean: ## Remove .venv and node_modules
+       rm -rf $(VENV) node_modules
diff --git a/dev/.rat-excludes b/dev/.rat-excludes
index bc614e9..5830bfb 100644
--- a/dev/.rat-excludes
+++ b/dev/.rat-excludes
@@ -19,6 +19,8 @@
 LICENSE
 NOTICE
 lib
+.venv/**
+node_modules/**
 
 # Fixture data and JSON Schemas have no comment syntax, so they cannot carry an
 # Apache header; they are covered by the repository LICENSE and NOTICE at the 
root.
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..5d42536
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,32 @@
+{
+  "name": "iceberg-verification",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "iceberg-verification",
+      "devDependencies": {
+        "prettier": "3.9.9"
+      },
+      "engines": {
+        "node": ">=20"
+      }
+    },
+    "node_modules/prettier": {
+      "version": "3.9.9",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.9.tgz";,
+      "integrity": 
"sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "prettier": "bin/prettier.cjs"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/prettier/prettier?sponsor=1";
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5fec251
--- /dev/null
+++ b/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "iceberg-verification",
+  "private": true,
+  "engines": {
+    "node": ">=20"
+  },
+  "devDependencies": {
+    "prettier": "3.9.9"
+  }
+}
diff --git a/table-spec/schema/core/cases.json 
b/table-spec/schema/core/cases.json
index ad7d4eb..a66a7bc 100644
--- a/table-spec/schema/core/cases.json
+++ b/table-spec/schema/core/cases.json
@@ -7,18 +7,8 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "data",
-            "required": false,
-            "type": "string"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "data", "required": false, "type": "string" }
         ]
       },
       "decoded": {
@@ -37,24 +27,9 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 3,
-            "name": "c",
-            "required": true,
-            "type": "int"
-          },
-          {
-            "id": 1,
-            "name": "a",
-            "required": true,
-            "type": "int"
-          },
-          {
-            "id": 2,
-            "name": "b",
-            "required": false,
-            "type": "int"
-          }
+          { "id": 3, "name": "c", "required": true, "type": "int" },
+          { "id": 1, "name": "a", "required": true, "type": "int" },
+          { "id": 2, "name": "b", "required": false, "type": "int" }
         ]
       },
       "decoded": {
@@ -74,12 +49,7 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "location",
@@ -87,18 +57,8 @@
             "type": {
               "type": "struct",
               "fields": [
-                {
-                  "id": 3,
-                  "name": "lat",
-                  "required": true,
-                  "type": "double"
-                },
-                {
-                  "id": 4,
-                  "name": "lon",
-                  "required": true,
-                  "type": "double"
-                }
+                { "id": 3, "name": "lat", "required": true, "type": "double" },
+                { "id": 4, "name": "lon", "required": true, "type": "double" }
               ]
             }
           }
@@ -122,22 +82,12 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "tags",
             "required": true,
-            "type": {
-              "type": "list",
-              "element-id": 3,
-              "element-required": false,
-              "element": "string"
-            }
+            "type": { "type": "list", "element-id": 3, "element-required": 
false, "element": "string" }
           }
         ]
       },
@@ -158,12 +108,7 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "props",
@@ -197,12 +142,7 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "points",
@@ -214,18 +154,8 @@
               "element": {
                 "type": "struct",
                 "fields": [
-                  {
-                    "id": 4,
-                    "name": "x",
-                    "required": true,
-                    "type": "int"
-                  },
-                  {
-                    "id": 5,
-                    "name": "y",
-                    "required": false,
-                    "type": "int"
-                  }
+                  { "id": 4, "name": "x", "required": true, "type": "int" },
+                  { "id": 5, "name": "y", "required": false, "type": "int" }
                 ]
               }
             }
@@ -251,12 +181,7 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "by_name",
@@ -267,17 +192,7 @@
               "key": "string",
               "value-id": 4,
               "value-required": false,
-              "value": {
-                "type": "struct",
-                "fields": [
-                  {
-                    "id": 5,
-                    "name": "count",
-                    "required": true,
-                    "type": "long"
-                  }
-                ]
-              }
+              "value": { "type": "struct", "fields": [{ "id": 5, "name": 
"count", "required": true, "type": "long" }] }
             }
           }
         ]
@@ -300,29 +215,11 @@
       "input": {
         "type": "struct",
         "schema-id": 7,
-        "identifier-field-ids": [
-          1,
-          2
-        ],
+        "identifier-field-ids": [1, 2],
         "fields": [
-          {
-            "id": 1,
-            "name": "tenant",
-            "required": true,
-            "type": "string"
-          },
-          {
-            "id": 2,
-            "name": "key",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 3,
-            "name": "payload",
-            "required": false,
-            "type": "string"
-          }
+          { "id": 1, "name": "tenant", "required": true, "type": "string" },
+          { "id": 2, "name": "key", "required": true, "type": "long" },
+          { "id": 3, "name": "payload", "required": false, "type": "string" }
         ]
       },
       "decoded": {
@@ -342,19 +239,8 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long",
-            "doc": "primary key"
-          },
-          {
-            "id": 2,
-            "name": "data",
-            "required": false,
-            "type": "string"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long", "doc": 
"primary key" },
+          { "id": 2, "name": "data", "required": false, "type": "string" }
         ]
       },
       "decoded": {
@@ -373,90 +259,20 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "f_boolean",
-            "required": false,
-            "type": "boolean"
-          },
-          {
-            "id": 2,
-            "name": "f_int",
-            "required": false,
-            "type": "int"
-          },
-          {
-            "id": 3,
-            "name": "f_long",
-            "required": false,
-            "type": "long"
-          },
-          {
-            "id": 4,
-            "name": "f_float",
-            "required": false,
-            "type": "float"
-          },
-          {
-            "id": 5,
-            "name": "f_double",
-            "required": false,
-            "type": "double"
-          },
-          {
-            "id": 6,
-            "name": "f_date",
-            "required": false,
-            "type": "date"
-          },
-          {
-            "id": 7,
-            "name": "f_time",
-            "required": false,
-            "type": "time"
-          },
-          {
-            "id": 8,
-            "name": "f_timestamp",
-            "required": false,
-            "type": "timestamp"
-          },
-          {
-            "id": 9,
-            "name": "f_timestamptz",
-            "required": false,
-            "type": "timestamptz"
-          },
-          {
-            "id": 10,
-            "name": "f_string",
-            "required": false,
-            "type": "string"
-          },
-          {
-            "id": 11,
-            "name": "f_uuid",
-            "required": false,
-            "type": "uuid"
-          },
-          {
-            "id": 12,
-            "name": "f_fixed",
-            "required": false,
-            "type": "fixed[16]"
-          },
-          {
-            "id": 13,
-            "name": "f_binary",
-            "required": false,
-            "type": "binary"
-          },
-          {
-            "id": 14,
-            "name": "f_decimal",
-            "required": false,
-            "type": "decimal(9, 2)"
-          }
+          { "id": 1, "name": "f_boolean", "required": false, "type": "boolean" 
},
+          { "id": 2, "name": "f_int", "required": false, "type": "int" },
+          { "id": 3, "name": "f_long", "required": false, "type": "long" },
+          { "id": 4, "name": "f_float", "required": false, "type": "float" },
+          { "id": 5, "name": "f_double", "required": false, "type": "double" },
+          { "id": 6, "name": "f_date", "required": false, "type": "date" },
+          { "id": 7, "name": "f_time", "required": false, "type": "time" },
+          { "id": 8, "name": "f_timestamp", "required": false, "type": 
"timestamp" },
+          { "id": 9, "name": "f_timestamptz", "required": false, "type": 
"timestamptz" },
+          { "id": 10, "name": "f_string", "required": false, "type": "string" 
},
+          { "id": 11, "name": "f_uuid", "required": false, "type": "uuid" },
+          { "id": 12, "name": "f_fixed", "required": false, "type": 
"fixed[16]" },
+          { "id": 13, "name": "f_binary", "required": false, "type": "binary" 
},
+          { "id": 14, "name": "f_decimal", "required": false, "type": 
"decimal(9, 2)" }
         ]
       },
       "decoded": {
@@ -474,9 +290,23 @@
           { "id": 9, "name": "f_timestamptz", "parent": null, "required": 
false, "type": "timestamptz", "doc": null },
           { "id": 10, "name": "f_string", "parent": null, "required": false, 
"type": "string", "doc": null },
           { "id": 11, "name": "f_uuid", "parent": null, "required": false, 
"type": "uuid", "doc": null },
-          { "id": 12, "name": "f_fixed", "parent": null, "required": false, 
"type": { "type": "fixed", "length": 16 }, "doc": null },
+          {
+            "id": 12,
+            "name": "f_fixed",
+            "parent": null,
+            "required": false,
+            "type": { "type": "fixed", "length": 16 },
+            "doc": null
+          },
           { "id": 13, "name": "f_binary", "parent": null, "required": false, 
"type": "binary", "doc": null },
-          { "id": 14, "name": "f_decimal", "parent": null, "required": false, 
"type": { "type": "decimal", "precision": 9, "scale": 2 }, "doc": null }
+          {
+            "id": 14,
+            "name": "f_decimal",
+            "parent": null,
+            "required": false,
+            "type": { "type": "decimal", "precision": 9, "scale": 2 },
+            "doc": null
+          }
         ]
       }
     },
@@ -487,18 +317,8 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "amount",
-            "required": false,
-            "type": "decimal(38, 10)"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "amount", "required": false, "type": "decimal(38, 
10)" }
         ]
       },
       "decoded": {
@@ -506,7 +326,14 @@
         "identifier-field-ids": [],
         "fields": [
           { "id": 1, "name": "id", "parent": null, "required": true, "type": 
"long", "doc": null },
-          { "id": 2, "name": "amount", "parent": null, "required": false, 
"type": { "type": "decimal", "precision": 38, "scale": 10 }, "doc": null }
+          {
+            "id": 2,
+            "name": "amount",
+            "parent": null,
+            "required": false,
+            "type": { "type": "decimal", "precision": 38, "scale": 10 },
+            "doc": null
+          }
         ]
       }
     },
@@ -516,17 +343,8 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          999
-        ],
-        "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          }
-        ]
+        "identifier-field-ids": [999],
+        "fields": [{ "id": 1, "name": "id", "required": true, "type": "long" }]
       }
     },
     {
@@ -535,22 +353,10 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          2
-        ],
+        "identifier-field-ids": [2],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "note",
-            "required": false,
-            "type": "string"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "note", "required": false, "type": "string" }
         ]
       }
     },
@@ -560,22 +366,10 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          2
-        ],
+        "identifier-field-ids": [2],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "score",
-            "required": true,
-            "type": "double"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "score", "required": true, "type": "double" }
         ]
       }
     },
@@ -585,22 +379,10 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          2
-        ],
+        "identifier-field-ids": [2],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "score",
-            "required": true,
-            "type": "float"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "score", "required": true, "type": "float" }
         ]
       }
     },
@@ -610,31 +392,14 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          2
-        ],
+        "identifier-field-ids": [2],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "loc",
             "required": true,
-            "type": {
-              "type": "struct",
-              "fields": [
-                {
-                  "id": 3,
-                  "name": "x",
-                  "required": true,
-                  "type": "long"
-                }
-              ]
-            }
+            "type": { "type": "struct", "fields": [{ "id": 3, "name": "x", 
"required": true, "type": "long" }] }
           }
         ]
       }
@@ -645,16 +410,9 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          4
-        ],
+        "identifier-field-ids": [4],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "rows",
@@ -663,17 +421,7 @@
               "type": "list",
               "element-id": 3,
               "element-required": true,
-              "element": {
-                "type": "struct",
-                "fields": [
-                  {
-                    "id": 4,
-                    "name": "k",
-                    "required": true,
-                    "type": "string"
-                  }
-                ]
-              }
+              "element": { "type": "struct", "fields": [{ "id": 4, "name": 
"k", "required": true, "type": "string" }] }
             }
           }
         ]
@@ -685,16 +433,9 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          5
-        ],
+        "identifier-field-ids": [5],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "rows",
@@ -705,17 +446,7 @@
               "key": "string",
               "value-id": 4,
               "value-required": true,
-              "value": {
-                "type": "struct",
-                "fields": [
-                  {
-                    "id": 5,
-                    "name": "k",
-                    "required": true,
-                    "type": "string"
-                  }
-                ]
-              }
+              "value": { "type": "struct", "fields": [{ "id": 5, "name": "k", 
"required": true, "type": "string" }] }
             }
           }
         ]
@@ -727,16 +458,9 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          3
-        ],
+        "identifier-field-ids": [3],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "props",
@@ -759,31 +483,14 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          3
-        ],
+        "identifier-field-ids": [3],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "key",
             "required": true,
-            "type": {
-              "type": "struct",
-              "fields": [
-                {
-                  "id": 3,
-                  "name": "part",
-                  "required": true,
-                  "type": "string"
-                }
-              ]
-            }
+            "type": { "type": "struct", "fields": [{ "id": 3, "name": "part", 
"required": true, "type": "string" }] }
           }
         ]
       },
@@ -803,31 +510,14 @@
       "input": {
         "type": "struct",
         "schema-id": 0,
-        "identifier-field-ids": [
-          3
-        ],
+        "identifier-field-ids": [3],
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
+          { "id": 1, "name": "id", "required": true, "type": "long" },
           {
             "id": 2,
             "name": "loc",
             "required": false,
-            "type": {
-              "type": "struct",
-              "fields": [
-                {
-                  "id": 3,
-                  "name": "x",
-                  "required": true,
-                  "type": "long"
-                }
-              ]
-            }
+            "type": { "type": "struct", "fields": [{ "id": 3, "name": "x", 
"required": true, "type": "long" }] }
           }
         ]
       }
diff --git a/table-spec/schema/unknown/cases.json 
b/table-spec/schema/unknown/cases.json
index 31c4d87..2da64fb 100644
--- a/table-spec/schema/unknown/cases.json
+++ b/table-spec/schema/unknown/cases.json
@@ -7,18 +7,8 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "future",
-            "required": false,
-            "type": "unknown"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "future", "required": false, "type": "unknown" }
         ]
       },
       "decoded": {
@@ -37,18 +27,8 @@
         "type": "struct",
         "schema-id": 0,
         "fields": [
-          {
-            "id": 1,
-            "name": "id",
-            "required": true,
-            "type": "long"
-          },
-          {
-            "id": 2,
-            "name": "future",
-            "required": true,
-            "type": "unknown"
-          }
+          { "id": 1, "name": "id", "required": true, "type": "long" },
+          { "id": 2, "name": "future", "required": true, "type": "unknown" }
         ]
       }
     }
diff --git a/table-spec/types/geospatial/cases.json 
b/table-spec/types/geospatial/cases.json
index 20a0f54..f5d8a7a 100644
--- a/table-spec/types/geospatial/cases.json
+++ b/table-spec/types/geospatial/cases.json
@@ -4,7 +4,7 @@
       "id": "geometry-crs84",
       "valid": true,
       "input": "geometry(OGC:CRS84)",
-      "decoded": {"type": "geometry", "crs": "OGC:CRS84"},
+      "decoded": { "type": "geometry", "crs": "OGC:CRS84" },
       "canonical": "geometry(OGC:CRS84)",
       "clause": "geometry(C) with explicit CRS; the canonical serialized form 
is the unquoted \"geometry(<C>)\"",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -13,7 +13,7 @@
       "id": "geometry-srid",
       "valid": true,
       "input": "geometry(srid:4326)",
-      "decoded": {"type": "geometry", "crs": "srid:4326"},
+      "decoded": { "type": "geometry", "crs": "srid:4326" },
       "canonical": "geometry(srid:4326)",
       "clause": "geometry(C) example from Appendix C is the unquoted 
\"geometry(srid:4326)\"",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -22,7 +22,7 @@
       "id": "geometry-default-crs",
       "valid": true,
       "input": "geometry",
-      "decoded": {"type": "geometry", "crs": "OGC:CRS84"},
+      "decoded": { "type": "geometry", "crs": "OGC:CRS84" },
       "clause": "geometry(C): if C is not specified, C is OGC:CRS84 
(spec.md:284-285); the read/parse direction is a MUST",
       "spec_ref": "format/spec.md#primitive-types"
     },
@@ -31,7 +31,7 @@
       "valid": true,
       "normative_level": "should",
       "input": "geometry",
-      "decoded": {"type": "geometry", "crs": "OGC:CRS84"},
+      "decoded": { "type": "geometry", "crs": "OGC:CRS84" },
       "canonical": "geometry(OGC:CRS84)",
       "clause": "geometry(C) re-serialize: Appendix C's canonical is fully 
parameterized, but whether a writer may elide the default is unsettled, so the 
write direction is advisory",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -40,7 +40,7 @@
       "id": "geography-crs84-spherical",
       "valid": true,
       "input": "geography(OGC:CRS84, spherical)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical" },
       "canonical": "geography(OGC:CRS84, spherical)",
       "clause": "geography(C, A) with explicit CRS and algorithm; the 
canonical serialized form is the unquoted \"geography(<C>, <A>)\"",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -49,7 +49,7 @@
       "id": "geography-default",
       "valid": true,
       "input": "geography",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical" },
       "clause": "geography(C, A): if not specified, C is OGC:CRS84 and A is 
spherical (spec.md:284-285); the read/parse direction is a MUST",
       "spec_ref": "format/spec.md#primitive-types"
     },
@@ -58,7 +58,7 @@
       "valid": true,
       "normative_level": "should",
       "input": "geography",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical" },
       "canonical": "geography(OGC:CRS84, spherical)",
       "clause": "geography(C, A) re-serialize: Appendix C's canonical is fully 
parameterized, but whether a writer may elide the defaults is unsettled, so the 
write direction is advisory",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -68,7 +68,7 @@
       "valid": true,
       "normative_level": "should",
       "input": "geography(OGC:CRS84)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"spherical" },
       "canonical": "geography(OGC:CRS84, spherical)",
       "clause": "geography(C): the 1-arg form (CRS given, algorithm omitted) 
is not in Appendix C grammar; cross-checked against Java reference behavior, 
which defaults A to spherical and re-serializes to the Appendix C canonical 
geography(<C>, <A>)",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
@@ -77,7 +77,7 @@
       "id": "geography-vincenty",
       "valid": true,
       "input": "geography(OGC:CRS84, vincenty)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"vincenty"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"vincenty" },
       "canonical": "geography(OGC:CRS84, vincenty)",
       "clause": "geography edge-interpolation algorithm vincenty (a v3 allowed 
algorithm)",
       "spec_ref": "format/spec.md#primitive-types"
@@ -86,7 +86,7 @@
       "id": "geography-thomas",
       "valid": true,
       "input": "geography(OGC:CRS84, thomas)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"thomas"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"thomas" },
       "canonical": "geography(OGC:CRS84, thomas)",
       "clause": "geography edge-interpolation algorithm thomas (a v3 allowed 
algorithm)",
       "spec_ref": "format/spec.md#primitive-types"
@@ -95,7 +95,7 @@
       "id": "geography-andoyer",
       "valid": true,
       "input": "geography(OGC:CRS84, andoyer)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"andoyer"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"andoyer" },
       "canonical": "geography(OGC:CRS84, andoyer)",
       "clause": "geography edge-interpolation algorithm andoyer (a v3 allowed 
algorithm)",
       "spec_ref": "format/spec.md#primitive-types"
@@ -104,7 +104,7 @@
       "id": "geography-karney",
       "valid": true,
       "input": "geography(OGC:CRS84, karney)",
-      "decoded": {"type": "geography", "crs": "OGC:CRS84", "algorithm": 
"karney"},
+      "decoded": { "type": "geography", "crs": "OGC:CRS84", "algorithm": 
"karney" },
       "canonical": "geography(OGC:CRS84, karney)",
       "clause": "geography edge-interpolation algorithm karney (a v3 allowed 
algorithm)",
       "spec_ref": "format/spec.md#primitive-types"
diff --git a/table-spec/types/nested/cases.json 
b/table-spec/types/nested/cases.json
index cb1d3b5..f00fa42 100644
--- a/table-spec/types/nested/cases.json
+++ b/table-spec/types/nested/cases.json
@@ -3,92 +3,146 @@
     {
       "id": "struct-single-field",
       "valid": true,
-      "input": {"type": "struct", "fields": [{"id": 1, "name": "a", 
"required": true, "type": "int"}]},
-      "decoded": {"type": "struct", "fields": [{"id": 1, "name": "a", 
"required": true, "type": {"type": "int"}}]},
+      "input": { "type": "struct", "fields": [{ "id": 1, "name": "a", 
"required": true, "type": "int" }] },
+      "decoded": {
+        "type": "struct",
+        "fields": [{ "id": 1, "name": "a", "required": true, "type": { "type": 
"int" } }]
+      },
       "clause": "struct is a tuple of typed fields; each field has an integer 
id, a name, a required flag, and a type",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "struct-empty",
       "valid": true,
-      "input": {"type": "struct", "fields": []},
-      "decoded": {"type": "struct", "fields": []},
+      "input": { "type": "struct", "fields": [] },
+      "decoded": { "type": "struct", "fields": [] },
       "clause": "a struct's fields array may be empty (Appendix C struct 
serialization)",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     },
     {
       "id": "struct-optional-field",
       "valid": true,
-      "input": {"type": "struct", "fields": [{"id": 1, "name": "a", 
"required": false, "type": "string"}]},
-      "decoded": {"type": "struct", "fields": [{"id": 1, "name": "a", 
"required": false, "type": {"type": "string"}}]},
+      "input": { "type": "struct", "fields": [{ "id": 1, "name": "a", 
"required": false, "type": "string" }] },
+      "decoded": {
+        "type": "struct",
+        "fields": [{ "id": 1, "name": "a", "required": false, "type": { 
"type": "string" } }]
+      },
       "clause": "each struct field can be optional or required (required=false 
permits null values)",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "list-required-element",
       "valid": true,
-      "input": {"type": "list", "element-id": 2, "element-required": true, 
"element": "string"},
-      "decoded": {"type": "list", "element-id": 2, "element-required": true, 
"element": {"type": "string"}},
+      "input": { "type": "list", "element-id": 2, "element-required": true, 
"element": "string" },
+      "decoded": { "type": "list", "element-id": 2, "element-required": true, 
"element": { "type": "string" } },
       "clause": "a list has an element type; the element field has an integer 
id and a required flag",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     },
     {
       "id": "list-optional-element",
       "valid": true,
-      "input": {"type": "list", "element-id": 2, "element-required": false, 
"element": "long"},
-      "decoded": {"type": "list", "element-id": 2, "element-required": false, 
"element": {"type": "long"}},
+      "input": { "type": "list", "element-id": 2, "element-required": false, 
"element": "long" },
+      "decoded": { "type": "list", "element-id": 2, "element-required": false, 
"element": { "type": "long" } },
       "clause": "list elements can be optional or required",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "map-string-double",
       "valid": true,
-      "input": {"type": "map", "key-id": 3, "key": "string", "value-id": 4, 
"value-required": false, "value": "double"},
-      "decoded": {"type": "map", "key-id": 3, "key": {"type": "string"}, 
"value-id": 4, "value-required": false, "value": {"type": "double"}},
+      "input": {
+        "type": "map",
+        "key-id": 3,
+        "key": "string",
+        "value-id": 4,
+        "value-required": false,
+        "value": "double"
+      },
+      "decoded": {
+        "type": "map",
+        "key-id": 3,
+        "key": { "type": "string" },
+        "value-id": 4,
+        "value-required": false,
+        "value": { "type": "double" }
+      },
       "clause": "a map has a key type and a value type; keys are required, 
values may be optional or required",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     },
     {
       "id": "struct-nested-list",
       "valid": true,
-      "input": {"type": "struct", "fields": [{"id": 1, "name": "tags", 
"required": true, "type": {"type": "list", "element-id": 2, "element-required": 
true, "element": "string"}}]},
-      "decoded": {"type": "struct", "fields": [{"id": 1, "name": "tags", 
"required": true, "type": {"type": "list", "element-id": 2, "element-required": 
true, "element": {"type": "string"}}}]},
+      "input": {
+        "type": "struct",
+        "fields": [
+          {
+            "id": 1,
+            "name": "tags",
+            "required": true,
+            "type": { "type": "list", "element-id": 2, "element-required": 
true, "element": "string" }
+          }
+        ]
+      },
+      "decoded": {
+        "type": "struct",
+        "fields": [
+          {
+            "id": 1,
+            "name": "tags",
+            "required": true,
+            "type": { "type": "list", "element-id": 2, "element-required": 
true, "element": { "type": "string" } }
+          }
+        ]
+      },
       "clause": "fields may be any type, including nested types (a struct 
field whose type is a list)",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "struct-field-missing-id",
       "valid": false,
-      "input": {"type": "struct", "fields": [{"name": "a", "required": true, 
"type": "int"}]},
+      "input": { "type": "struct", "fields": [{ "name": "a", "required": true, 
"type": "int" }] },
       "clause": "each field in a struct has an integer id; a field without an 
id is invalid",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "map-string-double-required",
       "valid": true,
-      "input": {"type": "map", "key-id": 3, "key": "string", "value-id": 4, 
"value-required": true, "value": "double"},
-      "decoded": {"type": "map", "key-id": 3, "key": {"type": "string"}, 
"value-id": 4, "value-required": true, "value": {"type": "double"}},
+      "input": {
+        "type": "map",
+        "key-id": 3,
+        "key": "string",
+        "value-id": 4,
+        "value-required": true,
+        "value": "double"
+      },
+      "decoded": {
+        "type": "map",
+        "key-id": 3,
+        "key": { "type": "string" },
+        "value-id": 4,
+        "value-required": true,
+        "value": { "type": "double" }
+      },
       "clause": "map values may be optional or required (value-required=true)",
       "spec_ref": "format/spec.md#nested-types"
     },
     {
       "id": "list-missing-element-id",
       "valid": false,
-      "input": {"type": "list", "element-required": true, "element": "string"},
+      "input": { "type": "list", "element-required": true, "element": "string" 
},
       "clause": "a list's element field has an integer element-id; a list 
without element-id is invalid",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     },
     {
       "id": "map-missing-key-id",
       "valid": false,
-      "input": {"type": "map", "key": "string", "value-id": 4, 
"value-required": false, "value": "double"},
+      "input": { "type": "map", "key": "string", "value-id": 4, 
"value-required": false, "value": "double" },
       "clause": "a map's key field has an integer key-id; a map without key-id 
is invalid",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     },
     {
       "id": "map-missing-value-id",
       "valid": false,
-      "input": {"type": "map", "key-id": 3, "key": "string", "value-required": 
false, "value": "double"},
+      "input": { "type": "map", "key-id": 3, "key": "string", 
"value-required": false, "value": "double" },
       "clause": "a map's value field has an integer value-id; a map without 
value-id is invalid",
       "spec_ref": "format/spec.md#appendix-c-json-serialization"
     }
diff --git a/table-spec/types/primitive/cases.json 
b/table-spec/types/primitive/cases.json
index 0b80383..784e4c5 100644
--- a/table-spec/types/primitive/cases.json
+++ b/table-spec/types/primitive/cases.json
@@ -1,34 +1,255 @@
 {
   "cases": [
-    { "id": "boolean", "valid": true, "input": "boolean", "decoded": { "type": 
"boolean" }, "canonical": "boolean", "clause": "Primitive Types: boolean; 
Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "int", "valid": true, "input": "int", "decoded": { "type": "int" 
}, "canonical": "int", "clause": "Primitive Types: int; Appendix C canonical 
string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "long", "valid": true, "input": "long", "decoded": { "type": 
"long" }, "canonical": "long", "clause": "Primitive Types: long; Appendix C 
canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "float", "valid": true, "input": "float", "decoded": { "type": 
"float" }, "canonical": "float", "clause": "Primitive Types: float; Appendix C 
canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "double", "valid": true, "input": "double", "decoded": { "type": 
"double" }, "canonical": "double", "clause": "Primitive Types: double; Appendix 
C canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" 
},
-    { "id": "date", "valid": true, "input": "date", "decoded": { "type": 
"date" }, "canonical": "date", "clause": "Primitive Types: date; Appendix C 
canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "time", "valid": true, "input": "time", "decoded": { "type": 
"time" }, "canonical": "time", "clause": "Primitive Types: time; Appendix C 
canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "timestamp", "valid": true, "input": "timestamp", "decoded": { 
"type": "timestamp" }, "canonical": "timestamp", "clause": "Primitive Types: 
timestamp; Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "timestamptz", "valid": true, "input": "timestamptz", "decoded": { 
"type": "timestamptz" }, "canonical": "timestamptz", "clause": "Primitive 
Types: timestamptz; Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "timestamp_ns", "valid": true, "input": "timestamp_ns", "decoded": 
{ "type": "timestamp_ns" }, "canonical": "timestamp_ns", "clause": "Primitive 
Types: timestamp_ns added in v3; Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "timestamptz_ns", "valid": true, "input": "timestamptz_ns", 
"decoded": { "type": "timestamptz_ns" }, "canonical": "timestamptz_ns", 
"clause": "Primitive Types: timestamptz_ns added in v3; Appendix C canonical 
string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "string", "valid": true, "input": "string", "decoded": { "type": 
"string" }, "canonical": "string", "clause": "Primitive Types: string; Appendix 
C canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" 
},
-    { "id": "uuid", "valid": true, "input": "uuid", "decoded": { "type": 
"uuid" }, "canonical": "uuid", "clause": "Primitive Types: uuid; Appendix C 
canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "binary", "valid": true, "input": "binary", "decoded": { "type": 
"binary" }, "canonical": "binary", "clause": "Primitive Types: binary; Appendix 
C canonical string", "spec_ref": "format/spec.md#appendix-c-json-serialization" 
},
-    { "id": "unknown", "valid": true, "input": "unknown", "decoded": { "type": 
"unknown" }, "canonical": "unknown", "clause": "Primitive Types: unknown added 
in v3; Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "fixed-1", "valid": true, "input": "fixed[1]", "decoded": { 
"type": "fixed", "length": 1 }, "canonical": "fixed[1]", "clause": "Appendix C: 
fixed canonical string is fixed[<L>]", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "fixed-16", "valid": true, "input": "fixed[16]", "decoded": { 
"type": "fixed", "length": 16 }, "canonical": "fixed[16]", "clause": "Appendix 
C: fixed canonical string is fixed[<L>]", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-9-2", "valid": true, "input": "decimal(9,2)", "decoded": 
{ "type": "decimal", "precision": 9, "scale": 2 }, "canonical": "decimal(9, 
2)", "clause": "Appendix C: the canonical serialized form is the spaced 
decimal(<P>, <S>); the no-space input re-serializes to it", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-9-2-spaced", "valid": true, "input": "decimal(9, 2)", 
"decoded": { "type": "decimal", "precision": 9, "scale": 2 }, "canonical": 
"decimal(9, 2)", "clause": "Appendix C canonical form is the spaced decimal(9, 
2); input is already canonical and re-serializes unchanged", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-9-2-spaced-params", "valid": true, "normative_level": 
"should", "input": "decimal( 9 , 2 )", "decoded": { "type": "decimal", 
"precision": 9, "scale": 2 }, "clause": "Appendix C: readers should accept 
optional whitespace around parameters and separators; a reader that rejects 
decimal( 9 , 2 ) is still conformant", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-38-0", "valid": true, "input": "decimal(38,0)", 
"decoded": { "type": "decimal", "precision": 38, "scale": 0 }, "clause": 
"Primitive Types: decimal precision must be 38 or less (38 is the maximum)", 
"spec_ref": "format/spec.md#primitive-types" },
-    { "id": "decimal-precision-over-38", "valid": false, "input": 
"decimal(39,0)", "clause": "Primitive Types: decimal precision must be 38 or 
less", "spec_ref": "format/spec.md#primitive-types" },
-    { "id": "decimal-missing-scale", "valid": false, "input": "decimal(9)", 
"clause": "Appendix C: decimal is written decimal(P,S); scale is required", 
"spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-empty-params", "valid": false, "input": "decimal()", 
"clause": "Appendix C: decimal requires precision and scale", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "decimal-non-numeric", "valid": false, "input": "decimal(a,b)", 
"clause": "Appendix C: decimal precision and scale are integers", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "fixed-empty-length", "valid": false, "input": "fixed[]", 
"clause": "Appendix C: fixed is written fixed[<L>]; length is required", 
"spec_ref": "format/spec.md#appendix-c-json-serialization" },
-    { "id": "fixed-unterminated", "valid": false, "input": "fixed[16", 
"clause": "Appendix C: fixed[<L>] must be closed with a bracket", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "fixed-non-numeric", "valid": false, "input": "fixed[abc]", 
"clause": "Appendix C: fixed length is an integer", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "empty-type", "valid": false, "input": "", "clause": "Primitive 
Types: the empty string is not a type name", "spec_ref": 
"format/spec.md#primitive-types" },
-    { "id": "unknown-type-name", "valid": false, "input": "notatype", 
"clause": "Primitive Types: only the listed type names are valid", "spec_ref": 
"format/spec.md#primitive-types" }
+    {
+      "id": "boolean",
+      "valid": true,
+      "input": "boolean",
+      "decoded": { "type": "boolean" },
+      "canonical": "boolean",
+      "clause": "Primitive Types: boolean; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "int",
+      "valid": true,
+      "input": "int",
+      "decoded": { "type": "int" },
+      "canonical": "int",
+      "clause": "Primitive Types: int; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "long",
+      "valid": true,
+      "input": "long",
+      "decoded": { "type": "long" },
+      "canonical": "long",
+      "clause": "Primitive Types: long; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "float",
+      "valid": true,
+      "input": "float",
+      "decoded": { "type": "float" },
+      "canonical": "float",
+      "clause": "Primitive Types: float; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "double",
+      "valid": true,
+      "input": "double",
+      "decoded": { "type": "double" },
+      "canonical": "double",
+      "clause": "Primitive Types: double; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "date",
+      "valid": true,
+      "input": "date",
+      "decoded": { "type": "date" },
+      "canonical": "date",
+      "clause": "Primitive Types: date; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "time",
+      "valid": true,
+      "input": "time",
+      "decoded": { "type": "time" },
+      "canonical": "time",
+      "clause": "Primitive Types: time; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "timestamp",
+      "valid": true,
+      "input": "timestamp",
+      "decoded": { "type": "timestamp" },
+      "canonical": "timestamp",
+      "clause": "Primitive Types: timestamp; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "timestamptz",
+      "valid": true,
+      "input": "timestamptz",
+      "decoded": { "type": "timestamptz" },
+      "canonical": "timestamptz",
+      "clause": "Primitive Types: timestamptz; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "timestamp_ns",
+      "valid": true,
+      "input": "timestamp_ns",
+      "decoded": { "type": "timestamp_ns" },
+      "canonical": "timestamp_ns",
+      "clause": "Primitive Types: timestamp_ns added in v3; Appendix C 
canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "timestamptz_ns",
+      "valid": true,
+      "input": "timestamptz_ns",
+      "decoded": { "type": "timestamptz_ns" },
+      "canonical": "timestamptz_ns",
+      "clause": "Primitive Types: timestamptz_ns added in v3; Appendix C 
canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "string",
+      "valid": true,
+      "input": "string",
+      "decoded": { "type": "string" },
+      "canonical": "string",
+      "clause": "Primitive Types: string; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "uuid",
+      "valid": true,
+      "input": "uuid",
+      "decoded": { "type": "uuid" },
+      "canonical": "uuid",
+      "clause": "Primitive Types: uuid; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "binary",
+      "valid": true,
+      "input": "binary",
+      "decoded": { "type": "binary" },
+      "canonical": "binary",
+      "clause": "Primitive Types: binary; Appendix C canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "unknown",
+      "valid": true,
+      "input": "unknown",
+      "decoded": { "type": "unknown" },
+      "canonical": "unknown",
+      "clause": "Primitive Types: unknown added in v3; Appendix C canonical 
string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "fixed-1",
+      "valid": true,
+      "input": "fixed[1]",
+      "decoded": { "type": "fixed", "length": 1 },
+      "canonical": "fixed[1]",
+      "clause": "Appendix C: fixed canonical string is fixed[<L>]",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "fixed-16",
+      "valid": true,
+      "input": "fixed[16]",
+      "decoded": { "type": "fixed", "length": 16 },
+      "canonical": "fixed[16]",
+      "clause": "Appendix C: fixed canonical string is fixed[<L>]",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-9-2",
+      "valid": true,
+      "input": "decimal(9,2)",
+      "decoded": { "type": "decimal", "precision": 9, "scale": 2 },
+      "canonical": "decimal(9, 2)",
+      "clause": "Appendix C: the canonical serialized form is the spaced 
decimal(<P>, <S>); the no-space input re-serializes to it",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-9-2-spaced",
+      "valid": true,
+      "input": "decimal(9, 2)",
+      "decoded": { "type": "decimal", "precision": 9, "scale": 2 },
+      "canonical": "decimal(9, 2)",
+      "clause": "Appendix C canonical form is the spaced decimal(9, 2); input 
is already canonical and re-serializes unchanged",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-9-2-spaced-params",
+      "valid": true,
+      "normative_level": "should",
+      "input": "decimal( 9 , 2 )",
+      "decoded": { "type": "decimal", "precision": 9, "scale": 2 },
+      "clause": "Appendix C: readers should accept optional whitespace around 
parameters and separators; a reader that rejects decimal( 9 , 2 ) is still 
conformant",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-38-0",
+      "valid": true,
+      "input": "decimal(38,0)",
+      "decoded": { "type": "decimal", "precision": 38, "scale": 0 },
+      "clause": "Primitive Types: decimal precision must be 38 or less (38 is 
the maximum)",
+      "spec_ref": "format/spec.md#primitive-types"
+    },
+    {
+      "id": "decimal-precision-over-38",
+      "valid": false,
+      "input": "decimal(39,0)",
+      "clause": "Primitive Types: decimal precision must be 38 or less",
+      "spec_ref": "format/spec.md#primitive-types"
+    },
+    {
+      "id": "decimal-missing-scale",
+      "valid": false,
+      "input": "decimal(9)",
+      "clause": "Appendix C: decimal is written decimal(P,S); scale is 
required",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-empty-params",
+      "valid": false,
+      "input": "decimal()",
+      "clause": "Appendix C: decimal requires precision and scale",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "decimal-non-numeric",
+      "valid": false,
+      "input": "decimal(a,b)",
+      "clause": "Appendix C: decimal precision and scale are integers",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "fixed-empty-length",
+      "valid": false,
+      "input": "fixed[]",
+      "clause": "Appendix C: fixed is written fixed[<L>]; length is required",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "fixed-unterminated",
+      "valid": false,
+      "input": "fixed[16",
+      "clause": "Appendix C: fixed[<L>] must be closed with a bracket",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "fixed-non-numeric",
+      "valid": false,
+      "input": "fixed[abc]",
+      "clause": "Appendix C: fixed length is an integer",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "empty-type",
+      "valid": false,
+      "input": "",
+      "clause": "Primitive Types: the empty string is not a type name",
+      "spec_ref": "format/spec.md#primitive-types"
+    },
+    {
+      "id": "unknown-type-name",
+      "valid": false,
+      "input": "notatype",
+      "clause": "Primitive Types: only the listed type names are valid",
+      "spec_ref": "format/spec.md#primitive-types"
+    }
   ]
 }
diff --git a/table-spec/types/variant/cases.json 
b/table-spec/types/variant/cases.json
index 4d92865..1fcf9bc 100644
--- a/table-spec/types/variant/cases.json
+++ b/table-spec/types/variant/cases.json
@@ -1,6 +1,20 @@
 {
   "cases": [
-    { "id": "variant", "valid": true, "input": "variant", "decoded": { "type": 
"variant" }, "canonical": "variant", "clause": "Semi-structured Types: variant 
added in v3; Appendix C canonical string", "spec_ref": 
"format/spec.md#appendix-c-json-serialization" },
-    { "id": "variant-with-params", "valid": false, "input": "variant(x)", 
"clause": "Appendix C: variant is a bare type name and takes no parameters", 
"spec_ref": "format/spec.md#appendix-c-json-serialization" }
+    {
+      "id": "variant",
+      "valid": true,
+      "input": "variant",
+      "decoded": { "type": "variant" },
+      "canonical": "variant",
+      "clause": "Semi-structured Types: variant added in v3; Appendix C 
canonical string",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    },
+    {
+      "id": "variant-with-params",
+      "valid": false,
+      "input": "variant(x)",
+      "clause": "Appendix C: variant is a bare type name and takes no 
parameters",
+      "spec_ref": "format/spec.md#appendix-c-json-serialization"
+    }
   ]
 }

Reply via email to