diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f824f63..a2cbcd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,15 +10,15 @@ 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 }} 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 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": { 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/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) { 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/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 { 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()); 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": { 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