From 360d56f0601446d6d2daffbe5d2395c418e1850a Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:13:43 -0500 Subject: [PATCH 1/8] Update dependencies for PHP 8 --- composer.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 702972a..139c54a 100644 --- a/composer.json +++ b/composer.json @@ -3,16 +3,17 @@ "description": "A utility library for working with Data Packages", "license": "MIT", "require": { - "php": ">=7.1", - "ext-zip": "*", - "justinrainbow/json-schema": "^5.2", - "frictionlessdata/tableschema": "^v1.0.0" + "php": ">=8", + "justinrainbow/json-schema": "^5.3 || ^6.6", + "frictionlessdata/tableschema": "^v1", + "ext-json": "*", + "ext-zip": "*" }, "require-dev": { - "phpunit/phpunit": "^7.5.20", - "satooshi/php-coveralls": "^1.0", + "phpunit/phpunit": ">=7.5 <10.0", + "php-coveralls/php-coveralls": "^2.4", "psy/psysh": "@stable", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { "psr-4": { From d9c79044649f659ae910d764431138166cb1efdb Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:15:29 -0500 Subject: [PATCH 2/8] Add return types for methods of classes implementing native PHP ones (e.g Iterator) Includes some smaller modernizations of code --- src/DataStreams/BaseDataStream.php | 2 +- src/DataStreams/DefaultDataStream.php | 13 +++++---- src/DataStreams/TabularDataStream.php | 18 ++++++------ src/Datapackages/BaseDatapackage.php | 40 +++++++++++++++++++++------ src/Resources/BaseResource.php | 20 ++++++++------ src/Resources/TabularResource.php | 7 +++-- src/Validators/BaseValidator.php | 12 ++++++-- 7 files changed, 77 insertions(+), 35 deletions(-) diff --git a/src/DataStreams/BaseDataStream.php b/src/DataStreams/BaseDataStream.php index fd2d766..c9ecbeb 100644 --- a/src/DataStreams/BaseDataStream.php +++ b/src/DataStreams/BaseDataStream.php @@ -30,5 +30,5 @@ abstract public function save($filename); * * @throws \frictionlessdata\datapackage\Exceptions\DataStreamValidationException */ - abstract public function current(); + abstract public function current():mixed; } diff --git a/src/DataStreams/DefaultDataStream.php b/src/DataStreams/DefaultDataStream.php index 7295e4b..340dae1 100644 --- a/src/DataStreams/DefaultDataStream.php +++ b/src/DataStreams/DefaultDataStream.php @@ -33,7 +33,10 @@ public function __destruct() fclose($this->fopenResource); } - public function rewind() + /** + * @throws \Exception + */ + public function rewind():void { if ($this->currentLineNumber == 0) { // starting iterations @@ -50,22 +53,22 @@ public function save($filename) fclose($target); } - public function current() + public function current():mixed { return fgets($this->fopenResource); } - public function key() + public function key():mixed { return $this->currentLineNumber; } - public function next() + public function next():void { ++$this->currentLineNumber; } - public function valid() + public function valid():bool { return !feof($this->fopenResource); } diff --git a/src/DataStreams/TabularDataStream.php b/src/DataStreams/TabularDataStream.php index 67b4ffe..bdf2786 100644 --- a/src/DataStreams/TabularDataStream.php +++ b/src/DataStreams/TabularDataStream.php @@ -15,6 +15,10 @@ class TabularDataStream extends BaseDataStream public $table; public $schema; + /** + * @throws \frictionlessdata\datapackage\Exceptions\DataStreamOpenException + * @throws \Exception + */ public function __construct($dataSource, $dataSourceOptions = null) { parent::__construct($dataSource, $dataSourceOptions); @@ -38,7 +42,7 @@ protected function getDataSourceObject() return new CsvDataSource($this->dataSource); } - public function rewind() + public function rewind():void { $this->table->rewind(); } @@ -53,28 +57,26 @@ public function save($filename) * * @throws DataStreamValidationException */ - public function current() + public function current():mixed { try { return $this->table->current(); - } catch (DataSourceException $e) { - throw new DataStreamValidationException($e->getMessage()); - } catch (FieldValidationException $e) { + } catch (DataSourceException|FieldValidationException $e) { throw new DataStreamValidationException($e->getMessage()); } } - public function key() + public function key():mixed { return $this->table->key(); } - public function next() + public function next():void { $this->table->next(); } - public function valid() + public function valid(): bool { return $this->table->valid(); } diff --git a/src/Datapackages/BaseDatapackage.php b/src/Datapackages/BaseDatapackage.php index b55c5ac..6bd981f 100644 --- a/src/Datapackages/BaseDatapackage.php +++ b/src/Datapackages/BaseDatapackage.php @@ -2,6 +2,7 @@ namespace frictionlessdata\datapackage\Datapackages; +use Exception; use frictionlessdata\datapackage\Factory; use frictionlessdata\datapackage\Package; use frictionlessdata\datapackage\Registry; @@ -9,9 +10,10 @@ use frictionlessdata\datapackage\Validators\DatapackageValidator; use frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException; use frictionlessdata\datapackage\Exceptions\DatapackageInvalidSourceException; +use Iterator; use ZipArchive; -abstract class BaseDatapackage implements \Iterator +abstract class BaseDatapackage implements Iterator { /** @@ -34,6 +36,9 @@ public function __construct($descriptor, $basePath = null, $skipValidations = fa } } + /** + * @throws \frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException + */ public static function create($name, $resources, $basePath = null) { $datapackage = new static((object) [ @@ -47,6 +52,9 @@ public static function create($name, $resources, $basePath = null) return $datapackage; } + /** + * @throws \frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException + */ public function revalidate() { $this->rewind(); @@ -81,6 +89,10 @@ public function resources() return $resources; } + /** + * @throws \frictionlessdata\datapackage\Exceptions\ResourceValidationFailedException + * @throws \Exception + */ public function getResource($name) { foreach ($this->descriptor->resources as $resourceDescriptor) { @@ -88,9 +100,12 @@ public function getResource($name) return $this->initResource($resourceDescriptor); } } - throw new \Exception("couldn't find matching resource with name = '{$name}'"); + throw new Exception("couldn't find matching resource with name = '{$name}'"); } + /** + * @throws \frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException + */ public function addResource($name, $resource) { if (is_a($resource, 'frictionlessdata\\datapackage\\Resources\\BaseResource')) { @@ -119,6 +134,10 @@ public function addResource($name, $resource) } // TODO: remove this function and use the getResource / addResource directly (will need to modify a lot of tests code) + + /** + * @throws \Exception + */ public function resource($name, $resource = null) { if ($resource) { @@ -128,6 +147,9 @@ public function resource($name, $resource = null) } } + /** + * @throws \frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException + */ public function removeResource($name) { $resourceDescriptors = []; @@ -148,27 +170,30 @@ public function saveDescriptor($filename) } // standard iterator functions - to iterate over the resources - public function rewind() + public function rewind():void { $this->currentResourcePosition = 0; } - public function current() + /** + * @throws \frictionlessdata\datapackage\Exceptions\ResourceValidationFailedException + */ + public function current():mixed { return $this->initResource($this->descriptor()->resources[$this->currentResourcePosition]); } - public function key() + public function key():mixed { return $this->currentResourcePosition; } - public function next() + public function next():void { ++$this->currentResourcePosition; } - public function valid() + public function valid():bool { return isset($this->descriptor()->resources[$this->currentResourcePosition]); } @@ -242,7 +267,6 @@ protected function copy() * @param object $descriptor * * @return \frictionlessdata\datapackage\Resources\BaseResource - * @throws \frictionlessdata\datapackage\Exceptions\ResourceValidationFailedException */ protected function initResource($descriptor) { diff --git a/src/Resources/BaseResource.php b/src/Resources/BaseResource.php index 70305b3..b53482e 100644 --- a/src/Resources/BaseResource.php +++ b/src/Resources/BaseResource.php @@ -8,6 +8,7 @@ use frictionlessdata\datapackage\Validators\ResourceValidator; use frictionlessdata\datapackage\Exceptions\ResourceValidationFailedException; use frictionlessdata\datapackage\Utils; +use frictionlessdata\tableschema\SchemaValidationError; abstract class BaseResource implements \Iterator { @@ -146,11 +147,11 @@ public function isRemote() public function data() { - return isset($this->descriptor()->data) ? $this->descriptor()->data : null; + return $this->descriptor()->data ?? null; } // standard iterator functions - to iterate over the data sources - public function rewind() + public function rewind():void { $this->dataStreams = null; $this->currentDataStream = 0; @@ -159,22 +160,25 @@ public function rewind() } } - public function current() + /** + * @throws \frictionlessdata\datapackage\Exceptions\DataStreamValidationException + */ + public function current():mixed { return $this->dataStreams()[$this->currentDataStream]->current(); } - public function key() + public function key():mixed { return $this->dataStreams()[$this->currentDataStream]->key(); } - public function next() + public function next():void { - return $this->dataStreams()[$this->currentDataStream]->next(); + $this->dataStreams()[$this->currentDataStream]->next(); } - public function valid() + public function valid():bool { $dataStreams = $this->dataStreams(); if ($dataStreams[$this->currentDataStream]->valid()) { @@ -223,7 +227,7 @@ public static function validateDataSource($dataSource, $basePath = null) $dataSource = static::normalizeDataSource($dataSource, $basePath); if (!Utils::isHttpSource($dataSource) && !file_exists($dataSource)) { $errors[] = new ResourceValidationError( - ResourceValidationError::SCHEMA_VIOLATION, + SchemaValidationError::SCHEMA_VIOLATION, "data source file does not exist or is not readable: {$dataSource}" ); } diff --git a/src/Resources/TabularResource.php b/src/Resources/TabularResource.php index edcca00..d4dd5e3 100644 --- a/src/Resources/TabularResource.php +++ b/src/Resources/TabularResource.php @@ -31,17 +31,20 @@ protected function getDataStream($dataSource, $dataSourceOptions = null) { $dataSourceOptions = array_merge([ 'schema' => $this->schema(), - 'dialect' => isset($this->descriptor()->dialect) ? $this->descriptor()->dialect : null, + 'dialect' => $this->descriptor()->dialect ?? null, ], (array) $dataSourceOptions); return new TabularDataStream($this->normalizeDataSource($dataSource, $this->basePath), $dataSourceOptions); } + /** + * @throws \frictionlessdata\datapackage\Exceptions\DataStreamOpenException + */ protected function getInlineDataStream($data) { return new TabularInlineDataStream($data, [ 'schema' => $this->schema(), - 'dialect' => isset($this->descriptor()->dialect) ? $this->descriptor()->dialect : null, + 'dialect' => $this->descriptor()->dialect ?? null, ]); } diff --git a/src/Validators/BaseValidator.php b/src/Validators/BaseValidator.php index 4c746f7..e46ff68 100644 --- a/src/Validators/BaseValidator.php +++ b/src/Validators/BaseValidator.php @@ -44,6 +44,9 @@ protected function getValidationProfile() return $this->descriptor->profile; } + /** + * @throws \Exception + */ protected function convertValidationSchemaFilenameToUrl($filename) { $filename = realpath($filename); @@ -116,9 +119,12 @@ protected function getValidationErrorMessage(array $error) return sprintf('[%s] %s', $error['property'], $error['message']); } - /** - * Does the validation, adds errors to the validator object using _addError method. - */ + /** + * Does the validation, adds errors to the validator object using _addError + * method. + * + * @throws \Exception + */ protected function validateSchema() { $this->validateSchemaUrl($this->getValidationSchemaUrl()); From 5a704bec41b42d4a0fd0eb39c1aeab20200616cc Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:16:45 -0500 Subject: [PATCH 3/8] Can't array_sum string values, use array_is_list (since 8.1) and count() instead also adds @throws annotation --- src/DataStreams/TabularInlineDataStream.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/DataStreams/TabularInlineDataStream.php b/src/DataStreams/TabularInlineDataStream.php index b24a9aa..a1f8a20 100644 --- a/src/DataStreams/TabularInlineDataStream.php +++ b/src/DataStreams/TabularInlineDataStream.php @@ -7,13 +7,27 @@ class TabularInlineDataStream extends TabularDataStream { + + /** + * @throws \frictionlessdata\datapackage\Exceptions\DataStreamOpenException + */ protected function getDataSourceObject() { $data = json_decode(json_encode($this->dataSource), true); if (is_array($data)) { $numFields = count($this->schema->fields()); $objRows = []; - if (array_sum(array_keys($data[0])) == array_sum(range(0, $numFields - 1))) { + if (!function_exists('array_is_list')) { + function array_is_list(array $arr):bool + { + if ($arr === []) { + return true; + } + return array_keys($arr) === range(0, count($arr) - 1); + } + } + + if (array_is_list($data[0]) && (count($data[0])) == $numFields) { // Row Arrays - convert to Row Objects $header = array_shift($data); foreach ($data as $row) { From ea4df86ebcf6c20bee6e3ff453c3de22599d5ddc Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:17:14 -0500 Subject: [PATCH 4/8] smaller simplications and use base CONSTANTS --- src/Factory.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index d48dc4e..15ad244 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -4,6 +4,7 @@ use frictionlessdata\datapackage\Datapackages\BaseDatapackage; use frictionlessdata\datapackage\Resources\BaseResource; +use frictionlessdata\tableschema\SchemaValidationError; use ZipArchive; /** @@ -39,9 +40,7 @@ public static function datapackage($source, $basePath = null) $descriptor = $source->descriptor; $basePath = $source->basePath; $datapackageClass = static::getDatapackageClass($descriptor); - $datapackage = new $datapackageClass($descriptor, $basePath); - - return $datapackage; + return new $datapackageClass($descriptor, $basePath); } /** @@ -94,7 +93,7 @@ public static function validate($source, $basePath = null) // return a list containing a single LOAD_FAILED validation error return [ new Validators\DatapackageValidationError( - Validators\DatapackageValidationError::LOAD_FAILED, + SchemaValidationError::LOAD_FAILED, $e->getMessage() ), ]; @@ -291,7 +290,7 @@ protected static function loadSource($source, $basePath) $basePath = null; } } else { - // not a json string and not a url - assume it's a file path + // not a json string and not an url - assume it's a file path if (static::isFileZipSource($source)) { return static::loadFileZipSource($source); } else { From 139b18ce56d34db45bc5fc016c531ff3cc584e1c Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:17:33 -0500 Subject: [PATCH 5/8] Update schemas --- src/Validators/schemas/CHANGELOG | 42 ++ src/Validators/schemas/data-package.json | 75 ++- src/Validators/schemas/data-resource.json | 35 +- .../schemas/fiscal-data-package.json | 488 ++++++++++++++---- src/Validators/schemas/table-schema.json | 156 +++++- .../schemas/tabular-data-package.json | 262 ++++++++-- .../schemas/tabular-data-resource.json | 226 ++++++-- 7 files changed, 1052 insertions(+), 232 deletions(-) diff --git a/src/Validators/schemas/CHANGELOG b/src/Validators/schemas/CHANGELOG index dcc64a0..38c917c 100644 --- a/src/Validators/schemas/CHANGELOG +++ b/src/Validators/schemas/CHANGELOG @@ -20,3 +20,45 @@ * default resource profile changed from 'default' to 'data-resource' * added 'data' - Inline data for this resource * changed source 'name' attribute to 'title' + + +Changes to data-package schema +2026-01-30T18:41:15+00:00 +* check the git diff and summarize the spec changes here +* + + + +Changes to tabular-data-package schema +2026-01-30T18:41:15+00:00 +* check the git diff and summarize the spec changes here +* + + + +Changes to fiscal-data-package schema +2026-01-30T18:41:15+00:00 +* check the git diff and summarize the spec changes here +* + + + +Changes to data-resource schema +2026-01-30T18:41:16+00:00 +* check the git diff and summarize the spec changes here +* + + + +Changes to tabular-data-resource schema +2026-01-30T18:41:16+00:00 +* check the git diff and summarize the spec changes here +* + + + +Changes to table-schema schema +2026-01-30T18:41:16+00:00 +* check the git diff and summarize the spec changes here +* + diff --git a/src/Validators/schemas/data-package.json b/src/Validators/schemas/data-package.json index 78d7386..9872902 100644 --- a/src/Validators/schemas/data-package.json +++ b/src/Validators/schemas/data-package.json @@ -101,8 +101,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -118,20 +119,13 @@ "{\n \"email\": \"example@example.com\"\n}\n" ] }, - "organisation": { + "organization": { "title": "Organization", "description": "An organizational affiliation for this contributor.", "type": "string" }, "role": { "type": "string", - "enum": [ - "publisher", - "author", - "maintainer", - "wrangler", - "contributor" - ], "default": "contributor" } }, @@ -178,6 +172,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -187,8 +193,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -208,7 +215,7 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "resources": { @@ -266,8 +273,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -279,8 +287,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -309,16 +318,19 @@ "propertyOrder": 40, "title": "Schema", "description": "A schema for this resource.", - "type": "object" + "type": [ + "string", + "object" + ] }, "title": { - "propertyOrder": 50, "title": "Title", "description": "A human-readable title.", "type": "string", "examples": [ "{\n \"title\": \"My Package Title\"\n}\n" - ] + ], + "propertyOrder": 50 }, "description": { "propertyOrder": 60, @@ -348,7 +360,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -367,8 +379,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -387,7 +400,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -403,6 +416,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -412,8 +437,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -433,7 +459,7 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "format": { @@ -506,7 +532,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -525,8 +551,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -545,7 +572,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] } } diff --git a/src/Validators/schemas/data-resource.json b/src/Validators/schemas/data-resource.json index 87f3f38..cc1790b 100644 --- a/src/Validators/schemas/data-resource.json +++ b/src/Validators/schemas/data-resource.json @@ -48,8 +48,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -61,8 +62,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -91,7 +93,10 @@ "propertyOrder": 40, "title": "Schema", "description": "A schema for this resource.", - "type": "object" + "type": [ + "string", + "object" + ] }, "title": { "propertyOrder": 50, @@ -130,7 +135,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -149,8 +154,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -169,7 +175,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -185,6 +191,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -194,8 +212,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -215,7 +234,7 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "format": { diff --git a/src/Validators/schemas/fiscal-data-package.json b/src/Validators/schemas/fiscal-data-package.json index 4067839..b4089f6 100644 --- a/src/Validators/schemas/fiscal-data-package.json +++ b/src/Validators/schemas/fiscal-data-package.json @@ -109,8 +109,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -126,20 +127,13 @@ "{\n \"email\": \"example@example.com\"\n}\n" ] }, - "organisation": { + "organization": { "title": "Organization", "description": "An organizational affiliation for this contributor.", "type": "string" }, "role": { "type": "string", - "enum": [ - "publisher", - "author", - "maintainer", - "wrangler", - "contributor" - ], "default": "contributor" } }, @@ -186,6 +180,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -195,8 +201,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -216,7 +223,7 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "resources": { @@ -280,8 +287,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -293,8 +301,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -323,7 +332,10 @@ "propertyOrder": 40, "title": "Table Schema", "description": "A Table Schema for this resource, compliant with the [Table Schema](/tableschema/) specification.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "fields" ], @@ -334,7 +346,7 @@ "items": { "title": "Table Schema Field", "type": "object", - "anyOf": [ + "oneOf": [ { "type": "object", "title": "String Field", @@ -364,6 +376,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `string`.", "enum": [ @@ -436,7 +456,8 @@ "description": "The field contains numbers of any kind including decimals.", "context": "The lexical formatting follows that of decimal in [XMLSchema](https://www.w3.org/TR/xmlschema-2/#decimal): a non-empty finite-length sequence of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, '+' is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: '-1.23', '12678967.543233', '+100000.00', '210'.\n\nThe following special string values are permitted (case does not need to be respected):\n - NaN: not a number\n - INF: positive infinity\n - -INF: negative infinity\n\nA number `MAY` also have a trailing:\n - exponent: this `MUST` consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)\n - percentage: the percentage sign: `%`. In conversion percentages should be divided by 100.\n\nIf both exponent and percentages are present the percentage `MUST` follow the exponent e.g. '53E10%' (equals 5.3).", "required": [ - "name" + "name", + "type" ], "properties": { "name": { @@ -460,6 +481,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `number`.", "enum": [ @@ -501,11 +530,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -589,6 +613,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `integer`.", "enum": [ @@ -622,11 +654,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -708,6 +735,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `date`.", "enum": [ @@ -790,6 +825,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `time`.", "enum": [ @@ -871,6 +914,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `datetime`.", "enum": [ @@ -952,6 +1003,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `year`.", "enum": [ @@ -1061,6 +1120,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `yearmonth`.", "enum": [ @@ -1088,11 +1155,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "type": "array", "minItems": 1, @@ -1149,12 +1211,27 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `boolean`.", "enum": [ "boolean" ] }, + "format": { + "description": "There are no format keyword options for `boolean`: only `default` is allowed.", + "enum": [ + "default" + ], + "default": "default" + }, "trueValues": { "type": "array", "minItems": 1, @@ -1240,6 +1317,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `object`.", "enum": [ @@ -1336,6 +1421,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geopoint`.", "enum": [ @@ -1439,6 +1532,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geojson`.", "enum": [ @@ -1538,6 +1639,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `array`.", "enum": [ @@ -1635,6 +1744,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `duration`.", "enum": [ @@ -1717,6 +1834,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `any`.", "enum": [ @@ -1861,7 +1986,6 @@ }, "missingValues": { "type": "array", - "minItems": 1, "items": { "type": "string" }, @@ -1871,7 +1995,8 @@ "description": "Values that when encountered in the source, should be considered as `null`, 'not present', or 'blank' values.", "context": "Many datasets arrive with missing data values, either because a value was not collected or it never existed.\nMissing values may be indicated simply by the value being empty in other cases a special value may have been used e.g. `-`, `NaN`, `0`, `-9999` etc.\nThe `missingValues` property provides a way to indicate that these values should be interpreted as equivalent to null.\n\n`missingValues` are strings rather than being the data type of the particular field. This allows for comparison prior to casting and for fields to have missing value which are not of their type, for example a `number` field to have missing values indicated by `-`.\n\nThe default value of `missingValue` for a non-string type field is the empty string `''`. For string type fields there is no default for `missingValue` (for string fields the empty string `''` is a valid value and need not indicate null).", "examples": [ - "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n" + "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n", + "{\n \"missingValues\": []\n}\n" ] } }, @@ -1880,23 +2005,23 @@ ] }, "title": { - "propertyOrder": 50, "title": "Title", "description": "A human-readable title.", "type": "string", "examples": [ "{\n \"title\": \"My Package Title\"\n}\n" - ] + ], + "propertyOrder": 50 }, "description": { - "propertyOrder": 60, - "format": "textarea", "title": "Description", "description": "A text description. Markdown is encouraged.", "type": "string", "examples": [ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" - ] + ], + "propertyOrder": 60, + "format": "textarea" }, "homepage": { "propertyOrder": 70, @@ -1916,7 +2041,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -1935,8 +2060,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -1955,7 +2081,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -1971,6 +2097,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -1980,8 +2118,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -2001,19 +2140,31 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "dialect": { "propertyOrder": 50, "title": "CSV Dialect", "description": "The CSV dialect descriptor.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "delimiter", "doubleQuote" ], "properties": { + "csvddfVersion": { + "title": "CSV Dialect schema version", + "description": "A number to indicate the schema version of CSV Dialect. Version 1.0 was named CSV Dialect Description Format and used different field names.", + "type": "number", + "default": 1.2, + "examples:": [ + "{\n \"csvddfVersion\": \"1.2\"\n}\n" + ] + }, "delimiter": { "title": "Delimiter", "description": "A character sequence to use as the field separator.", @@ -2058,15 +2209,13 @@ "type": "string", "default": "\"", "examples": [ - "{\n \"quoteChar\": \"\"\n}\n", - "{\n \"quoteChar\": \"''\"\n}\n" + "{\n \"quoteChar\": \"'\"\n}\n" ] }, "escapeChar": { "title": "Escape Character", "description": "Specifies a one-character string to use as the escape character.", "type": "string", - "default": "\\", "examples": [ "{\n \"escapeChar\": \"\\\\\"\n}\n" ] @@ -2075,7 +2224,7 @@ "title": "Skip Initial Space", "description": "Specifies the interpretation of whitespace immediately following a delimiter. If false, whitespace immediately after a delimiter should be treated as part of the subsequent field.", "type": "boolean", - "default": true, + "default": false, "examples": [ "{\n \"skipInitialSpace\": true\n}\n" ] @@ -2089,6 +2238,14 @@ "{\n \"header\": true\n}\n" ] }, + "commentChar": { + "title": "Comment Character", + "description": "Specifies that any row beginning with this one-character string, without preceeding whitespace, causes the entire line to be ignored.", + "type": "string", + "examples": [ + "{\n \"commentChar\": \"#\"\n}\n" + ] + }, "caseSensitiveHeader": { "title": "Case Sensitive Header", "description": "Specifies if the case of headers is meaningful.", @@ -2102,7 +2259,7 @@ }, "examples": [ "{\n \"dialect\": {\n \"delimiter\": \";\"\n }\n}\n", - "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"''\"\n }\n}\n" + "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"'\",\n \"commentChar\": \"#\"\n }\n}\n" ] }, "format": { @@ -2175,7 +2332,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -2194,8 +2351,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -2214,7 +2372,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] } } @@ -2286,8 +2444,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -2299,8 +2458,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -2329,7 +2489,10 @@ "propertyOrder": 40, "title": "Table Schema", "description": "A Table Schema for this resource, compliant with the [Table Schema](/tableschema/) specification.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "fields" ], @@ -2340,7 +2503,7 @@ "items": { "title": "Table Schema Field", "type": "object", - "anyOf": [ + "oneOf": [ { "type": "object", "title": "String Field", @@ -2370,6 +2533,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `string`.", "enum": [ @@ -2442,7 +2613,8 @@ "description": "The field contains numbers of any kind including decimals.", "context": "The lexical formatting follows that of decimal in [XMLSchema](https://www.w3.org/TR/xmlschema-2/#decimal): a non-empty finite-length sequence of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, '+' is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: '-1.23', '12678967.543233', '+100000.00', '210'.\n\nThe following special string values are permitted (case does not need to be respected):\n - NaN: not a number\n - INF: positive infinity\n - -INF: negative infinity\n\nA number `MAY` also have a trailing:\n - exponent: this `MUST` consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)\n - percentage: the percentage sign: `%`. In conversion percentages should be divided by 100.\n\nIf both exponent and percentages are present the percentage `MUST` follow the exponent e.g. '53E10%' (equals 5.3).", "required": [ - "name" + "name", + "type" ], "properties": { "name": { @@ -2466,6 +2638,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `number`.", "enum": [ @@ -2507,11 +2687,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -2595,6 +2770,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `integer`.", "enum": [ @@ -2628,11 +2811,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -2714,6 +2892,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `date`.", "enum": [ @@ -2796,6 +2982,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `time`.", "enum": [ @@ -2877,6 +3071,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `datetime`.", "enum": [ @@ -2958,6 +3160,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `year`.", "enum": [ @@ -3067,6 +3277,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `yearmonth`.", "enum": [ @@ -3094,11 +3312,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "type": "array", "minItems": 1, @@ -3155,12 +3368,27 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `boolean`.", "enum": [ "boolean" ] }, + "format": { + "description": "There are no format keyword options for `boolean`: only `default` is allowed.", + "enum": [ + "default" + ], + "default": "default" + }, "trueValues": { "type": "array", "minItems": 1, @@ -3246,6 +3474,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `object`.", "enum": [ @@ -3342,6 +3578,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geopoint`.", "enum": [ @@ -3445,6 +3689,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geojson`.", "enum": [ @@ -3544,6 +3796,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `array`.", "enum": [ @@ -3641,6 +3901,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `duration`.", "enum": [ @@ -3723,6 +3991,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `any`.", "enum": [ @@ -3867,7 +4143,6 @@ }, "missingValues": { "type": "array", - "minItems": 1, "items": { "type": "string" }, @@ -3877,7 +4152,8 @@ "description": "Values that when encountered in the source, should be considered as `null`, 'not present', or 'blank' values.", "context": "Many datasets arrive with missing data values, either because a value was not collected or it never existed.\nMissing values may be indicated simply by the value being empty in other cases a special value may have been used e.g. `-`, `NaN`, `0`, `-9999` etc.\nThe `missingValues` property provides a way to indicate that these values should be interpreted as equivalent to null.\n\n`missingValues` are strings rather than being the data type of the particular field. This allows for comparison prior to casting and for fields to have missing value which are not of their type, for example a `number` field to have missing values indicated by `-`.\n\nThe default value of `missingValue` for a non-string type field is the empty string `''`. For string type fields there is no default for `missingValue` (for string fields the empty string `''` is a valid value and need not indicate null).", "examples": [ - "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n" + "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n", + "{\n \"missingValues\": []\n}\n" ] } }, @@ -3886,23 +4162,23 @@ ] }, "title": { - "propertyOrder": 50, "title": "Title", "description": "A human-readable title.", "type": "string", "examples": [ "{\n \"title\": \"My Package Title\"\n}\n" - ] + ], + "propertyOrder": 50 }, "description": { - "propertyOrder": 60, - "format": "textarea", "title": "Description", "description": "A text description. Markdown is encouraged.", "type": "string", "examples": [ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" - ] + ], + "propertyOrder": 60, + "format": "textarea" }, "homepage": { "propertyOrder": 70, @@ -3922,7 +4198,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -3941,8 +4217,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -3961,7 +4238,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -3977,6 +4254,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -3986,8 +4275,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -4007,19 +4297,31 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "dialect": { "propertyOrder": 50, "title": "CSV Dialect", "description": "The CSV dialect descriptor.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "delimiter", "doubleQuote" ], "properties": { + "csvddfVersion": { + "title": "CSV Dialect schema version", + "description": "A number to indicate the schema version of CSV Dialect. Version 1.0 was named CSV Dialect Description Format and used different field names.", + "type": "number", + "default": 1.2, + "examples:": [ + "{\n \"csvddfVersion\": \"1.2\"\n}\n" + ] + }, "delimiter": { "title": "Delimiter", "description": "A character sequence to use as the field separator.", @@ -4064,15 +4366,13 @@ "type": "string", "default": "\"", "examples": [ - "{\n \"quoteChar\": \"\"\n}\n", - "{\n \"quoteChar\": \"''\"\n}\n" + "{\n \"quoteChar\": \"'\"\n}\n" ] }, "escapeChar": { "title": "Escape Character", "description": "Specifies a one-character string to use as the escape character.", "type": "string", - "default": "\\", "examples": [ "{\n \"escapeChar\": \"\\\\\"\n}\n" ] @@ -4081,7 +4381,7 @@ "title": "Skip Initial Space", "description": "Specifies the interpretation of whitespace immediately following a delimiter. If false, whitespace immediately after a delimiter should be treated as part of the subsequent field.", "type": "boolean", - "default": true, + "default": false, "examples": [ "{\n \"skipInitialSpace\": true\n}\n" ] @@ -4095,6 +4395,14 @@ "{\n \"header\": true\n}\n" ] }, + "commentChar": { + "title": "Comment Character", + "description": "Specifies that any row beginning with this one-character string, without preceeding whitespace, causes the entire line to be ignored.", + "type": "string", + "examples": [ + "{\n \"commentChar\": \"#\"\n}\n" + ] + }, "caseSensitiveHeader": { "title": "Case Sensitive Header", "description": "Specifies if the case of headers is meaningful.", @@ -4108,7 +4416,7 @@ }, "examples": [ "{\n \"dialect\": {\n \"delimiter\": \";\"\n }\n}\n", - "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"''\"\n }\n}\n" + "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"'\",\n \"commentChar\": \"#\"\n }\n}\n" ] }, "format": { diff --git a/src/Validators/schemas/table-schema.json b/src/Validators/schemas/table-schema.json index 28e74ce..b828f44 100644 --- a/src/Validators/schemas/table-schema.json +++ b/src/Validators/schemas/table-schema.json @@ -2,7 +2,10 @@ "$schema": "http://json-schema.org/draft-04/schema#", "title": "Table Schema", "description": "A Table Schema for this resource, compliant with the [Table Schema](/tableschema/) specification.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "fields" ], @@ -13,7 +16,7 @@ "items": { "title": "Table Schema Field", "type": "object", - "anyOf": [ + "oneOf": [ { "type": "object", "title": "String Field", @@ -43,6 +46,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `string`.", "enum": [ @@ -115,7 +126,8 @@ "description": "The field contains numbers of any kind including decimals.", "context": "The lexical formatting follows that of decimal in [XMLSchema](https://www.w3.org/TR/xmlschema-2/#decimal): a non-empty finite-length sequence of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, '+' is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: '-1.23', '12678967.543233', '+100000.00', '210'.\n\nThe following special string values are permitted (case does not need to be respected):\n - NaN: not a number\n - INF: positive infinity\n - -INF: negative infinity\n\nA number `MAY` also have a trailing:\n - exponent: this `MUST` consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)\n - percentage: the percentage sign: `%`. In conversion percentages should be divided by 100.\n\nIf both exponent and percentages are present the percentage `MUST` follow the exponent e.g. '53E10%' (equals 5.3).", "required": [ - "name" + "name", + "type" ], "properties": { "name": { @@ -139,6 +151,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `number`.", "enum": [ @@ -180,11 +200,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -268,6 +283,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `integer`.", "enum": [ @@ -301,11 +324,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -387,6 +405,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `date`.", "enum": [ @@ -469,6 +495,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `time`.", "enum": [ @@ -550,6 +584,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `datetime`.", "enum": [ @@ -631,6 +673,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `year`.", "enum": [ @@ -740,6 +790,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `yearmonth`.", "enum": [ @@ -767,11 +825,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "type": "array", "minItems": 1, @@ -828,12 +881,27 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `boolean`.", "enum": [ "boolean" ] }, + "format": { + "description": "There are no format keyword options for `boolean`: only `default` is allowed.", + "enum": [ + "default" + ], + "default": "default" + }, "trueValues": { "type": "array", "minItems": 1, @@ -919,6 +987,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `object`.", "enum": [ @@ -1015,6 +1091,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geopoint`.", "enum": [ @@ -1118,6 +1202,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geojson`.", "enum": [ @@ -1217,6 +1309,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `array`.", "enum": [ @@ -1314,6 +1414,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `duration`.", "enum": [ @@ -1396,6 +1504,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `any`.", "enum": [ @@ -1540,7 +1656,6 @@ }, "missingValues": { "type": "array", - "minItems": 1, "items": { "type": "string" }, @@ -1550,7 +1665,8 @@ "description": "Values that when encountered in the source, should be considered as `null`, 'not present', or 'blank' values.", "context": "Many datasets arrive with missing data values, either because a value was not collected or it never existed.\nMissing values may be indicated simply by the value being empty in other cases a special value may have been used e.g. `-`, `NaN`, `0`, `-9999` etc.\nThe `missingValues` property provides a way to indicate that these values should be interpreted as equivalent to null.\n\n`missingValues` are strings rather than being the data type of the particular field. This allows for comparison prior to casting and for fields to have missing value which are not of their type, for example a `number` field to have missing values indicated by `-`.\n\nThe default value of `missingValue` for a non-string type field is the empty string `''`. For string type fields there is no default for `missingValue` (for string fields the empty string `''` is a valid value and need not indicate null).", "examples": [ - "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n" + "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n", + "{\n \"missingValues\": []\n}\n" ] } }, diff --git a/src/Validators/schemas/tabular-data-package.json b/src/Validators/schemas/tabular-data-package.json index 9bbdc94..aff781e 100644 --- a/src/Validators/schemas/tabular-data-package.json +++ b/src/Validators/schemas/tabular-data-package.json @@ -104,8 +104,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -121,20 +122,13 @@ "{\n \"email\": \"example@example.com\"\n}\n" ] }, - "organisation": { + "organization": { "title": "Organization", "description": "An organizational affiliation for this contributor.", "type": "string" }, "role": { "type": "string", - "enum": [ - "publisher", - "author", - "maintainer", - "wrangler", - "contributor" - ], "default": "contributor" } }, @@ -181,6 +175,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -190,8 +196,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -211,7 +218,7 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "resources": { @@ -275,8 +282,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -288,8 +296,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -318,7 +327,10 @@ "propertyOrder": 40, "title": "Table Schema", "description": "A Table Schema for this resource, compliant with the [Table Schema](/tableschema/) specification.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "fields" ], @@ -329,7 +341,7 @@ "items": { "title": "Table Schema Field", "type": "object", - "anyOf": [ + "oneOf": [ { "type": "object", "title": "String Field", @@ -359,6 +371,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `string`.", "enum": [ @@ -431,7 +451,8 @@ "description": "The field contains numbers of any kind including decimals.", "context": "The lexical formatting follows that of decimal in [XMLSchema](https://www.w3.org/TR/xmlschema-2/#decimal): a non-empty finite-length sequence of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, '+' is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: '-1.23', '12678967.543233', '+100000.00', '210'.\n\nThe following special string values are permitted (case does not need to be respected):\n - NaN: not a number\n - INF: positive infinity\n - -INF: negative infinity\n\nA number `MAY` also have a trailing:\n - exponent: this `MUST` consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)\n - percentage: the percentage sign: `%`. In conversion percentages should be divided by 100.\n\nIf both exponent and percentages are present the percentage `MUST` follow the exponent e.g. '53E10%' (equals 5.3).", "required": [ - "name" + "name", + "type" ], "properties": { "name": { @@ -455,6 +476,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `number`.", "enum": [ @@ -496,11 +525,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -584,6 +608,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `integer`.", "enum": [ @@ -617,11 +649,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -703,6 +730,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `date`.", "enum": [ @@ -785,6 +820,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `time`.", "enum": [ @@ -866,6 +909,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `datetime`.", "enum": [ @@ -947,6 +998,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `year`.", "enum": [ @@ -1056,6 +1115,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `yearmonth`.", "enum": [ @@ -1083,11 +1150,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "type": "array", "minItems": 1, @@ -1144,12 +1206,27 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `boolean`.", "enum": [ "boolean" ] }, + "format": { + "description": "There are no format keyword options for `boolean`: only `default` is allowed.", + "enum": [ + "default" + ], + "default": "default" + }, "trueValues": { "type": "array", "minItems": 1, @@ -1235,6 +1312,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `object`.", "enum": [ @@ -1331,6 +1416,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geopoint`.", "enum": [ @@ -1434,6 +1527,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geojson`.", "enum": [ @@ -1533,6 +1634,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `array`.", "enum": [ @@ -1630,6 +1739,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `duration`.", "enum": [ @@ -1712,6 +1829,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `any`.", "enum": [ @@ -1856,7 +1981,6 @@ }, "missingValues": { "type": "array", - "minItems": 1, "items": { "type": "string" }, @@ -1866,7 +1990,8 @@ "description": "Values that when encountered in the source, should be considered as `null`, 'not present', or 'blank' values.", "context": "Many datasets arrive with missing data values, either because a value was not collected or it never existed.\nMissing values may be indicated simply by the value being empty in other cases a special value may have been used e.g. `-`, `NaN`, `0`, `-9999` etc.\nThe `missingValues` property provides a way to indicate that these values should be interpreted as equivalent to null.\n\n`missingValues` are strings rather than being the data type of the particular field. This allows for comparison prior to casting and for fields to have missing value which are not of their type, for example a `number` field to have missing values indicated by `-`.\n\nThe default value of `missingValue` for a non-string type field is the empty string `''`. For string type fields there is no default for `missingValue` (for string fields the empty string `''` is a valid value and need not indicate null).", "examples": [ - "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n" + "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n", + "{\n \"missingValues\": []\n}\n" ] } }, @@ -1875,23 +2000,23 @@ ] }, "title": { - "propertyOrder": 50, "title": "Title", "description": "A human-readable title.", "type": "string", "examples": [ "{\n \"title\": \"My Package Title\"\n}\n" - ] + ], + "propertyOrder": 50 }, "description": { - "propertyOrder": 60, - "format": "textarea", "title": "Description", "description": "A text description. Markdown is encouraged.", "type": "string", "examples": [ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" - ] + ], + "propertyOrder": 60, + "format": "textarea" }, "homepage": { "propertyOrder": 70, @@ -1911,7 +2036,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -1930,8 +2055,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -1950,7 +2076,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -1966,6 +2092,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -1975,8 +2113,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -1996,19 +2135,31 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "dialect": { "propertyOrder": 50, "title": "CSV Dialect", "description": "The CSV dialect descriptor.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "delimiter", "doubleQuote" ], "properties": { + "csvddfVersion": { + "title": "CSV Dialect schema version", + "description": "A number to indicate the schema version of CSV Dialect. Version 1.0 was named CSV Dialect Description Format and used different field names.", + "type": "number", + "default": 1.2, + "examples:": [ + "{\n \"csvddfVersion\": \"1.2\"\n}\n" + ] + }, "delimiter": { "title": "Delimiter", "description": "A character sequence to use as the field separator.", @@ -2053,15 +2204,13 @@ "type": "string", "default": "\"", "examples": [ - "{\n \"quoteChar\": \"\"\n}\n", - "{\n \"quoteChar\": \"''\"\n}\n" + "{\n \"quoteChar\": \"'\"\n}\n" ] }, "escapeChar": { "title": "Escape Character", "description": "Specifies a one-character string to use as the escape character.", "type": "string", - "default": "\\", "examples": [ "{\n \"escapeChar\": \"\\\\\"\n}\n" ] @@ -2070,7 +2219,7 @@ "title": "Skip Initial Space", "description": "Specifies the interpretation of whitespace immediately following a delimiter. If false, whitespace immediately after a delimiter should be treated as part of the subsequent field.", "type": "boolean", - "default": true, + "default": false, "examples": [ "{\n \"skipInitialSpace\": true\n}\n" ] @@ -2084,6 +2233,14 @@ "{\n \"header\": true\n}\n" ] }, + "commentChar": { + "title": "Comment Character", + "description": "Specifies that any row beginning with this one-character string, without preceeding whitespace, causes the entire line to be ignored.", + "type": "string", + "examples": [ + "{\n \"commentChar\": \"#\"\n}\n" + ] + }, "caseSensitiveHeader": { "title": "Case Sensitive Header", "description": "Specifies if the case of headers is meaningful.", @@ -2097,7 +2254,7 @@ }, "examples": [ "{\n \"dialect\": {\n \"delimiter\": \";\"\n }\n}\n", - "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"''\"\n }\n}\n" + "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"'\",\n \"commentChar\": \"#\"\n }\n}\n" ] }, "format": { @@ -2170,7 +2327,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -2189,8 +2346,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -2209,7 +2367,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] } } diff --git a/src/Validators/schemas/tabular-data-resource.json b/src/Validators/schemas/tabular-data-resource.json index def495e..48fb75d 100644 --- a/src/Validators/schemas/tabular-data-resource.json +++ b/src/Validators/schemas/tabular-data-resource.json @@ -54,8 +54,9 @@ "oneOf": [ { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -67,8 +68,9 @@ "minItems": 1, "items": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -97,7 +99,10 @@ "propertyOrder": 40, "title": "Table Schema", "description": "A Table Schema for this resource, compliant with the [Table Schema](/tableschema/) specification.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "fields" ], @@ -108,7 +113,7 @@ "items": { "title": "Table Schema Field", "type": "object", - "anyOf": [ + "oneOf": [ { "type": "object", "title": "String Field", @@ -138,6 +143,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `string`.", "enum": [ @@ -210,7 +223,8 @@ "description": "The field contains numbers of any kind including decimals.", "context": "The lexical formatting follows that of decimal in [XMLSchema](https://www.w3.org/TR/xmlschema-2/#decimal): a non-empty finite-length sequence of decimal digits separated by a period as a decimal indicator. An optional leading sign is allowed. If the sign is omitted, '+' is assumed. Leading and trailing zeroes are optional. If the fractional part is zero, the period and following zero(es) can be omitted. For example: '-1.23', '12678967.543233', '+100000.00', '210'.\n\nThe following special string values are permitted (case does not need to be respected):\n - NaN: not a number\n - INF: positive infinity\n - -INF: negative infinity\n\nA number `MAY` also have a trailing:\n - exponent: this `MUST` consist of an E followed by an optional + or - sign followed by one or more decimal digits (0-9)\n - percentage: the percentage sign: `%`. In conversion percentages should be divided by 100.\n\nIf both exponent and percentages are present the percentage `MUST` follow the exponent e.g. '53E10%' (equals 5.3).", "required": [ - "name" + "name", + "type" ], "properties": { "name": { @@ -234,6 +248,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `number`.", "enum": [ @@ -275,11 +297,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -363,6 +380,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `integer`.", "enum": [ @@ -396,11 +421,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "oneOf": [ { @@ -482,6 +502,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `date`.", "enum": [ @@ -564,6 +592,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `time`.", "enum": [ @@ -645,6 +681,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `datetime`.", "enum": [ @@ -726,6 +770,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `year`.", "enum": [ @@ -835,6 +887,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `yearmonth`.", "enum": [ @@ -862,11 +922,6 @@ "type": "boolean", "description": "When `true`, each value for the property `MUST` be unique." }, - "pattern": { - "type": "string", - "description": "A regular expression pattern to test each value of the property against, where a truthy response indicates validity.", - "context": "Regular expressions `SHOULD` conform to the [XML Schema regular expression syntax](http://www.w3.org/TR/xmlschema-2/#regexs)." - }, "enum": { "type": "array", "minItems": 1, @@ -923,12 +978,27 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `boolean`.", "enum": [ "boolean" ] }, + "format": { + "description": "There are no format keyword options for `boolean`: only `default` is allowed.", + "enum": [ + "default" + ], + "default": "default" + }, "trueValues": { "type": "array", "minItems": 1, @@ -1014,6 +1084,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `object`.", "enum": [ @@ -1110,6 +1188,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geopoint`.", "enum": [ @@ -1213,6 +1299,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `geojson`.", "enum": [ @@ -1312,6 +1406,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `array`.", "enum": [ @@ -1409,6 +1511,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `duration`.", "enum": [ @@ -1491,6 +1601,14 @@ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" ] }, + "example": { + "title": "Example", + "description": "An example value for the field.", + "type": "string", + "examples": [ + "{\n \"example\": \"Put here an example value for your field\"\n}\n" + ] + }, "type": { "description": "The type keyword, which `MUST` be a value of `any`.", "enum": [ @@ -1635,7 +1753,6 @@ }, "missingValues": { "type": "array", - "minItems": 1, "items": { "type": "string" }, @@ -1645,7 +1762,8 @@ "description": "Values that when encountered in the source, should be considered as `null`, 'not present', or 'blank' values.", "context": "Many datasets arrive with missing data values, either because a value was not collected or it never existed.\nMissing values may be indicated simply by the value being empty in other cases a special value may have been used e.g. `-`, `NaN`, `0`, `-9999` etc.\nThe `missingValues` property provides a way to indicate that these values should be interpreted as equivalent to null.\n\n`missingValues` are strings rather than being the data type of the particular field. This allows for comparison prior to casting and for fields to have missing value which are not of their type, for example a `number` field to have missing values indicated by `-`.\n\nThe default value of `missingValue` for a non-string type field is the empty string `''`. For string type fields there is no default for `missingValue` (for string fields the empty string `''` is a valid value and need not indicate null).", "examples": [ - "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n" + "{\n \"missingValues\": [\n \"-\",\n \"NaN\",\n \"\"\n ]\n}\n", + "{\n \"missingValues\": []\n}\n" ] } }, @@ -1654,23 +1772,23 @@ ] }, "title": { - "propertyOrder": 50, "title": "Title", "description": "A human-readable title.", "type": "string", "examples": [ "{\n \"title\": \"My Package Title\"\n}\n" - ] + ], + "propertyOrder": 50 }, "description": { - "propertyOrder": 60, - "format": "textarea", "title": "Description", "description": "A text description. Markdown is encouraged.", "type": "string", "examples": [ "{\n \"description\": \"# My Package description\\nAll about my package.\"\n}\n" - ] + ], + "propertyOrder": 60, + "format": "textarea" }, "homepage": { "propertyOrder": 70, @@ -1690,7 +1808,7 @@ "title": "Sources", "description": "The raw sources for this resource.", "type": "array", - "minItems": 1, + "minItems": 0, "items": { "title": "Source", "description": "A source file.", @@ -1709,8 +1827,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -1729,7 +1848,7 @@ } }, "examples": [ - "{\n \"sources\": [\n {\n \"name\": \"World Bank and OECD\",\n \"uri\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" + "{\n \"sources\": [\n {\n \"title\": \"World Bank and OECD\",\n \"path\": \"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD\"\n }\n ]\n}\n" ] }, "licenses": { @@ -1745,6 +1864,18 @@ "title": "License", "description": "A license for this descriptor.", "type": "object", + "anyOf": [ + { + "required": [ + "name" + ] + }, + { + "required": [ + "path" + ] + } + ], "properties": { "name": { "title": "Open Definition license identifier", @@ -1754,8 +1885,9 @@ }, "path": { "title": "Path", - "description": "A fully qualified URL, or a POSIX file path..", + "description": "A fully qualified URL, or a POSIX file path.", "type": "string", + "pattern": "^(?=^[^./~])(^((?!\\.{2}).)*$).*$", "examples": [ "{\n \"path\": \"file.csv\"\n}\n", "{\n \"path\": \"http://example.com/file.csv\"\n}\n" @@ -1775,19 +1907,31 @@ }, "context": "This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.", "examples": [ - "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"uri\": \"http://opendatacommons.org/licenses/pddl/\"\n }\n ]\n}\n" + "{\n \"licenses\": [\n {\n \"name\": \"odc-pddl-1.0\",\n \"path\": \"http://opendatacommons.org/licenses/pddl/\",\n \"title\": \"Open Data Commons Public Domain Dedication and License v1.0\"\n }\n ]\n}\n" ] }, "dialect": { "propertyOrder": 50, "title": "CSV Dialect", "description": "The CSV dialect descriptor.", - "type": "object", + "type": [ + "string", + "object" + ], "required": [ "delimiter", "doubleQuote" ], "properties": { + "csvddfVersion": { + "title": "CSV Dialect schema version", + "description": "A number to indicate the schema version of CSV Dialect. Version 1.0 was named CSV Dialect Description Format and used different field names.", + "type": "number", + "default": 1.2, + "examples:": [ + "{\n \"csvddfVersion\": \"1.2\"\n}\n" + ] + }, "delimiter": { "title": "Delimiter", "description": "A character sequence to use as the field separator.", @@ -1832,15 +1976,13 @@ "type": "string", "default": "\"", "examples": [ - "{\n \"quoteChar\": \"\"\n}\n", - "{\n \"quoteChar\": \"''\"\n}\n" + "{\n \"quoteChar\": \"'\"\n}\n" ] }, "escapeChar": { "title": "Escape Character", "description": "Specifies a one-character string to use as the escape character.", "type": "string", - "default": "\\", "examples": [ "{\n \"escapeChar\": \"\\\\\"\n}\n" ] @@ -1849,7 +1991,7 @@ "title": "Skip Initial Space", "description": "Specifies the interpretation of whitespace immediately following a delimiter. If false, whitespace immediately after a delimiter should be treated as part of the subsequent field.", "type": "boolean", - "default": true, + "default": false, "examples": [ "{\n \"skipInitialSpace\": true\n}\n" ] @@ -1863,6 +2005,14 @@ "{\n \"header\": true\n}\n" ] }, + "commentChar": { + "title": "Comment Character", + "description": "Specifies that any row beginning with this one-character string, without preceeding whitespace, causes the entire line to be ignored.", + "type": "string", + "examples": [ + "{\n \"commentChar\": \"#\"\n}\n" + ] + }, "caseSensitiveHeader": { "title": "Case Sensitive Header", "description": "Specifies if the case of headers is meaningful.", @@ -1876,7 +2026,7 @@ }, "examples": [ "{\n \"dialect\": {\n \"delimiter\": \";\"\n }\n}\n", - "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"''\"\n }\n}\n" + "{\n \"dialect\": {\n \"delimiter\": \"\\t\",\n \"quoteChar\": \"'\",\n \"commentChar\": \"#\"\n }\n}\n" ] }, "format": { From 339d98393d4142e8ecebe95205a5b8a25a859018 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:18:53 -0500 Subject: [PATCH 6/8] Small fix for Fiscal DataPackage test, primary keys, in this case ID (from table package) can't be NULL Means, fix the CSV + a small typo fix since i was there --- tests/DatapackageTest.php | 7 +++---- tests/fixtures/fiscal-datapackage/budget.csv | 2 +- tests/fixtures/fiscal-datapackage/entities.csv | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/DatapackageTest.php b/tests/DatapackageTest.php index 44d16d2..d559f67 100644 --- a/tests/DatapackageTest.php +++ b/tests/DatapackageTest.php @@ -22,8 +22,7 @@ class DatapackageTest extends TestCase public $simpleDescriptorExpectedData; public $fixturesPath; - public function setUp() - { + public function setUp(): void { $this->simpleDescriptorArray = [ 'name' => 'datapackage-name', 'resources' => [ @@ -356,7 +355,7 @@ public function testFiscalDatapackage() } } $this->assertEquals([ - 'id' => null, 'amount' => null, 'date' => null, 'payee' => 1, + 'id' => 2, 'amount' => null, 'date' => null, 'payee' => '1', ], $resources_data['budget'][1]); $this->assertEquals([ 'id' => '1', 'title' => null, 'description' => 'They are the first acme company', @@ -437,7 +436,7 @@ public function testCreateEditDatapackageDescriptor() foreach ($resource as $row) { } } catch (Exceptions\DataStreamOpenException $e) { - $this->assertContains('Failed to open tabular data source', $e->getMessage()); + $this->assertStringContainsString('Failed to open tabular data source', $e->getMessage()); } } } diff --git a/tests/fixtures/fiscal-datapackage/budget.csv b/tests/fixtures/fiscal-datapackage/budget.csv index 146465d..cbb22e5 100644 --- a/tests/fixtures/fiscal-datapackage/budget.csv +++ b/tests/fixtures/fiscal-datapackage/budget.csv @@ -1,3 +1,3 @@ -pk,budget,budget_date,payee +id,budget,budget_date,payee 1,10000,01/01/2015,1 2,20000,01/02/2015,1 \ No newline at end of file diff --git a/tests/fixtures/fiscal-datapackage/entities.csv b/tests/fixtures/fiscal-datapackage/entities.csv index 31ef80c..b09bf81 100644 --- a/tests/fixtures/fiscal-datapackage/entities.csv +++ b/tests/fixtures/fiscal-datapackage/entities.csv @@ -1,3 +1,3 @@ id,name,description 1,Acme 1,They are the first acme company -2,Acme 2,They are the sceond acme company \ No newline at end of file +2,Acme 2,They are the second acme company \ No newline at end of file From cfb0dfd0910f90d4bb61a39a427b61fe68153458 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:23:20 -0500 Subject: [PATCH 7/8] Test only on PHP 8.1 and 8.3 8.4 will fail bc of CSV loading requiring explicit defaults for delimiter, escape characters, etc (which requires changes on frictionlessdata/tableschema too) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f824f63..6b81d47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-versions: ['7.1', '7.4'] + php-versions: ['8.1', '8.3'] name: frictionlessdata/datapackage-php PHP ${{ matrix.php-versions }} test on ${{ matrix.operating-system }} From 37bdf5164de97d95b9dde30468073c9ce062a824 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 30 Jan 2026 14:28:12 -0500 Subject: [PATCH 8/8] Update CI actions versions --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b81d47..a2cbcd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,10 +15,10 @@ jobs: name: frictionlessdata/datapackage-php PHP ${{ matrix.php-versions }} test on ${{ matrix.operating-system }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - name: Cache Composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/composer-cache key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} @@ -33,7 +33,7 @@ jobs: uses: php-actions/composer@v6 with: php_version: ${{ matrix.php-versions }} - php_extensions: zip + php_extensions: zip json version: 2 command: validate --strict @@ -41,7 +41,7 @@ jobs: uses: php-actions/composer@v6 with: php_version: ${{ matrix.php-versions }} - php_extensions: zip + php_extensions: zip json version: 2 dev: yes command: style-check @@ -50,7 +50,7 @@ jobs: uses: php-actions/composer@v6 with: php_version: ${{ matrix.php-versions }} - php_extensions: zip + php_extensions: zip json dev: yes command: test