From f5cd531e1c040252be2c1e55237fcef071188e27 Mon Sep 17 00:00:00 2001 From: pkdash Date: Tue, 30 Jan 2024 17:45:06 -0500 Subject: [PATCH] [#38] moving json schema customization to base class --- api/models/schema.py | 338 ++---- api/models/schemas/schema.json | 1917 +++++++++++++++----------------- 2 files changed, 981 insertions(+), 1274 deletions(-) diff --git a/api/models/schema.py b/api/models/schema.py index 4d3989d..864e33c 100644 --- a/api/models/schema.py +++ b/api/models/schema.py @@ -1,12 +1,14 @@ import re +import typing from datetime import datetime from enum import Enum from typing import Any, List, Optional, Union, Literal - +import pydantic_core from pydantic_core import CoreSchema from pydantic import ( BaseModel, + ConfigDict, EmailStr, Field, HttpUrl, @@ -74,6 +76,55 @@ def remove_default_empty_list(cls, field_schema: dict[str, Any]) -> dict[str, An field_schema.pop("default") return field_schema + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + # adjusting the json schema to make the UI work + json_schema = handler(core_schema) + json_schema = handler.resolve_ref_schema(json_schema) + for field, field_info in cls.model_fields.items(): + if field not in json_schema["properties"]: + continue + # check if the field is an optional field + if ( + type(field_info.annotation) is typing._UnionGenericAlias + and type(None) in field_info.annotation.__args__ + ): + # check if the field is also a union type + if len(field_info.annotation.__args__) > 2: + # remove the null type from the union type + field_schema = json_schema["properties"][field] + field_schema["anyOf"] = [ + item + for item in field_schema["anyOf"] + if item != {"type": "null"} + ] + else: + # field is not a union type - remove the anyOf key + field_schema = cls.remove_any_of(json_schema, field) + # check if the field is an url type + if HttpUrlStr in field_info.annotation.__args__: + field_schema = cls.update_url_schema(field_schema) + for data_type in field_info.annotation.__args__: + origin_data_type = typing.get_origin(data_type) + if origin_data_type is list: + field_schema = cls.remove_default_empty_list(field_schema) + break + field_schema = cls.remove_default_null(field_schema) + json_schema["properties"][field] = field_schema + else: + # field is not optional + if field in json_schema["properties"]: + field_schema = json_schema["properties"][field] + # check if the field is an url type + if field_info.annotation is pydantic_core._pydantic_core.Url: + field_schema = cls.update_url_schema(field_schema) + field_schema = cls.remove_default_null(field_schema) + json_schema["properties"][field] = field_schema + + return json_schema + class CreativeWork(SchemaBaseModel): type: str = Field( @@ -85,27 +136,6 @@ class CreativeWork(SchemaBaseModel): name: str = Field(description="Submission's name or title", title="Name or title") -class _CreativeWorkMixin(CreativeWork): - """Mixin class for CreativeWork models to custom generate json schema""" - - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for url and description optional fields - # we are doing this because the schema based UI is currently not able to handle the anyOf key with - # two possible types - one of which is null (due to the field being optional) - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("url", "description"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.update_url_schema(field_schema) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - - class Person(SchemaBaseModel): type: Literal["Person"] = Field( alias="@type", @@ -125,23 +155,6 @@ class Person(SchemaBaseModel): default=[], ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for email and identifier optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("email", "identifier"): - field_schema = cls.remove_any_of(json_schema, field) - if field == "email": - field_schema = cls.remove_default_null(field_schema) - else: - field_schema = cls.remove_default_empty_list(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - class Organization(SchemaBaseModel): type: Literal["Organization"] = Field( @@ -161,21 +174,6 @@ class Organization(SchemaBaseModel): default=None, ) # Should address be a string or another constrained type? - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for url and address optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("url", "address"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.update_url_schema(field_schema) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - class Affiliation(Organization): name: str = Field( @@ -202,21 +200,6 @@ class Provider(Person): default=None, ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key and default key for email, identifier and affiliation - # optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("email", "identifier", "affiliation"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - class Creator(Person): identifier: Optional[str] = Field( @@ -237,36 +220,9 @@ class Creator(Person): default=None, ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for affiliation optional field - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("email", "identifier", "affiliation"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - class FunderOrganization(Organization): - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("url", "address"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.update_url_schema(field_schema) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - json_schema.update(title="Funding Organization") - return json_schema - + model_config = ConfigDict(title="Funding Organization") name: str = Field(description="Name of the organization.") @@ -280,19 +236,11 @@ class PublisherOrganization(Organization): class MediaObjectSourceOrganization(Organization): + model_config = ConfigDict(title="Media Object Source Organization") name: str = Field( description="Name of the organization that created the media object." ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - json_schema["title"] = "Media Object Source Organization" - return json_schema - class DefinedTerm(SchemaBaseModel): type: str = Field(alias="@type", default="DefinedTerm") @@ -336,7 +284,7 @@ class Published(DefinedTerm): ) -class HasPart(_CreativeWorkMixin): +class HasPart(CreativeWork): url: Optional[HttpUrlStr] = Field( title="URL", description="The URL address to the data resource.", default=None ) @@ -346,7 +294,7 @@ class HasPart(_CreativeWorkMixin): ) -class IsPartOf(_CreativeWorkMixin): +class IsPartOf(CreativeWork): url: Optional[HttpUrlStr] = Field( title="URL", description="The URL address to the data resource.", default=None ) @@ -357,7 +305,7 @@ class IsPartOf(_CreativeWorkMixin): ) -class SubjectOf(_CreativeWorkMixin): +class SubjectOf(CreativeWork): url: Optional[HttpUrlStr] = Field( title="URL", description="The URL address that serves as a reference to access additional details related to the record. " @@ -372,7 +320,7 @@ class SubjectOf(_CreativeWorkMixin): ) -class License(_CreativeWorkMixin): +class License(CreativeWork): name: str = Field( description="A text string indicating the name of the license under which the resource is shared." ) @@ -434,19 +382,6 @@ class Grant(SchemaBaseModel): default=None, ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for description, identifier, and funder optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("description", "identifier", "funder"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - return json_schema - class TemporalCoverage(SchemaBaseModel): startDate: datetime = Field( @@ -467,19 +402,6 @@ class TemporalCoverage(SchemaBaseModel): default=None, ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for endDate optional field - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("endDate",): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - return json_schema - class GeoCoordinates(SchemaBaseModel): type: str = Field( @@ -551,6 +473,8 @@ def validate_box(cls, v): class PropertyValueBase(SchemaBaseModel): + model_config = ConfigDict(title="Property Value") + type: str = Field( alias="@type", default="PropertyValue", @@ -597,19 +521,6 @@ def validate_min_max_values(cls, values): return values - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - json_schema["title"] = "Property Value" - for field in ("propertyID", "unitCode", "description", "minValue", "maxValue"): - field_schema = cls.remove_any_of(json_schema, field) - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - return json_schema - class PropertyValue(PropertyValueBase): # using PropertyValueBase model instead of PropertyValue model as one of the types for the value field @@ -648,36 +559,6 @@ def validate_geo_or_name_required(cls, values): ) return values - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for name and additionalProperty optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ( - "name", - "additionalProperty", - ): - field_schema = cls.remove_any_of(json_schema, field) - if field == "name": - field_schema = cls.remove_default_null(field_schema) - else: - field_schema = cls.remove_default_empty_list(field_schema) - json_schema["properties"][field] = field_schema - - # adjusting the schema to remove the dict item {"type": "null"} from the list of types in anyOf - # for geo optional field - for field in ("geo",): - field_schema = json_schema["properties"][field] - field_schema["anyOf"] = [ - item for item in field_schema["anyOf"] if item != {"type": "null"} - ] - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - class MediaObject(SchemaBaseModel): type: str = Field( @@ -725,37 +606,6 @@ class MediaObject(SchemaBaseModel): default=None, ) - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - # adjusting the schema for the contentUrl field - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ("contentUrl",): - field_schema = json_schema["properties"][field] - field_schema = cls.update_url_schema(field_schema) - json_schema["properties"][field] = field_schema - # adjusting the schema for optional fields - for field in ( - "additionalProperty", - "variableMeasured", - "spatialCoverage", - "temporalCoverage", - "sourceOrganization", - ): - field_schema = json_schema["properties"][field] - field_schema["anyOf"] = [ - item for item in field_schema["anyOf"] if item != {"type": "null"} - ] - if field in ("additionalProperty", "variableMeasured"): - field_schema = cls.remove_default_empty_list(field_schema) - else: - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - return json_schema - @field_validator("contentSize") def validate_content_size(cls, v): v = v.strip() @@ -919,69 +769,11 @@ class CoreMetadata(SchemaBaseModel): def __get_pydantic_json_schema__( cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler ) -> JsonSchemaValue: - # adjusting the schema to remove the anyOf key for all the optional fields - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - for field in ( - "identifier", - "publisher", - "datePublished", - "subjectOf", - "version", - "dateModified", - "funding", - "temporalCoverage", - "spatialCoverage", - "hasPart", - "isPartOf", - "associatedMedia", - "citation", - ): - field_schema = cls.remove_any_of(json_schema, field) - json_schema["properties"][field] = field_schema - - # adjusting the schema to remove the dict item {"type": "null"} from the list of types in anyOf for - # inLanguage and creativeWorkStatus optional fields - for field in ("inLanguage", "creativeWorkStatus"): - field_schema = json_schema["properties"][field] - field_schema["anyOf"] = [ - item for item in field_schema["anyOf"] if item != {"type": "null"} - ] - json_schema["properties"][field] = field_schema - - for field in ("@context", "url"): - field_schema = json_schema["properties"][field] - field_schema = cls.update_url_schema(field_schema) - json_schema["properties"][field] = field_schema - - # remove the default value of null from the schema for these optional fields - for field in ( - "datePublished", - "dateModified", - "temporalCoverage", - "spatialCoverage", - "publisher", - "creativeWorkStatus", - "inLanguage", - "version", - ): - field_schema = json_schema["properties"][field] - field_schema = cls.remove_default_null(field_schema) - json_schema["properties"][field] = field_schema - - # remove the default value of an empty list from the schema for these optional fields - for field in ( - "identifier", - "subjectOf", - "funding", - "hasPart", - "isPartOf", - "associatedMedia", - "citation", - ): - field_schema = json_schema["properties"][field] - field_schema = cls.remove_default_empty_list(field_schema) - json_schema["properties"][field] = field_schema + json_schema = super().__get_pydantic_json_schema__(core_schema, handler) + field = "@context" + field_schema = json_schema["properties"][field] + field_schema = cls.update_url_schema(field_schema) + json_schema["properties"][field] = field_schema return json_schema diff --git a/api/models/schemas/schema.json b/api/models/schemas/schema.json index d43e49f..e0f4a08 100644 --- a/api/models/schemas/schema.json +++ b/api/models/schemas/schema.json @@ -459,9 +459,178 @@ "type": "string" }, "additionalProperty": { - "anyOf": [ - { - "items": { + "description": "Additional properties of the media object.", + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + { + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "type": "array" + } + ], + "description": "The value of the property.", + "title": "Value" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "title": "Additional properties", + "type": "array" + }, + "variableMeasured": { + "description": "Measured variables.", + "items": { + "anyOf": [ + { + "type": "string" + }, + { "properties": { "@type": { "default": "PropertyValue", @@ -620,510 +789,305 @@ ], "title": "Property Value", "type": "object" - }, - "type": "array" - } - ], - "description": "Additional properties of the media object.", - "title": "Additional properties" + } + ] + }, + "title": "Variables measured", + "type": "array" }, - "variableMeasured": { - "anyOf": [ - { + "spatialCoverage": { + "properties": { + "@type": { + "default": "Place", + "description": "Represents the focus area of the record's content.", + "title": "@Type", + "type": "string" + }, + "name": { + "description": "Name of the place.", + "title": "Name", + "type": "string" + }, + "geo": { + "anyOf": [ + { + "properties": { + "@type": { + "default": "GeoCoordinates", + "description": "Geographic coordinates that represent a specific location on the Earth's surface. GeoCoordinates typically consists of two components: latitude and longitude.", + "title": "@Type", + "type": "string" + }, + "latitude": { + "description": "Represents the angular distance of a location north or south of the equator, measured in degrees and ranges from -90 to +90 degrees.", + "title": "Latitude", + "type": "number" + }, + "longitude": { + "description": "Represents the angular distance of a location east or west of the Prime Meridian, measured in degrees and ranges from -180 to +180 degrees.", + "title": "Longitude", + "type": "number" + } + }, + "required": [ + "latitude", + "longitude" + ], + "title": "GeoCoordinates", + "type": "object" + }, + { + "properties": { + "@type": { + "default": "GeoShape", + "description": "A structured representation that describes the coordinates of a geographic feature.", + "title": "@Type", + "type": "string" + }, + "box": { + "description": "A box is a rectangular region defined by a pair of coordinates representing the southwest and northeast corners of the box.", + "title": "Box", + "type": "string" + } + }, + "required": [ + "box" + ], + "title": "GeoShape", + "type": "object" + } + ], + "description": "Specifies the geographic coordinates of the place in the form of a point location, line, or area coverage extent.", + "title": "Geo" + }, + "additionalProperty": { + "description": "Additional properties of the place.", "items": { - "anyOf": [ - { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", "type": "string" }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "anyOf": [ + { "type": "string" }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "anyOf": [ - { + { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", "type": "string" }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" }, - { - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - }, - "type": "array" - } - ], - "description": "The value of the property.", - "title": "Value" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - } - ] - }, - "type": "array" - } - ], - "description": "Measured variables.", - "title": "Variables measured" - }, - "spatialCoverage": { - "anyOf": [ - { - "properties": { - "@type": { - "default": "Place", - "description": "Represents the focus area of the record's content.", - "title": "@Type", - "type": "string" - }, - "name": { - "description": "Name of the place.", - "title": "Name", - "type": "string" - }, - "geo": { - "anyOf": [ - { - "properties": { - "@type": { - "default": "GeoCoordinates", - "description": "Geographic coordinates that represent a specific location on the Earth's surface. GeoCoordinates typically consists of two components: latitude and longitude.", - "title": "@Type", - "type": "string" - }, - "latitude": { - "description": "Represents the angular distance of a location north or south of the equator, measured in degrees and ranges from -90 to +90 degrees.", - "title": "Latitude", - "type": "number" - }, - "longitude": { - "description": "Represents the angular distance of a location east or west of the Prime Meridian, measured in degrees and ranges from -180 to +180 degrees.", - "title": "Longitude", - "type": "number" - } - }, - "required": [ - "latitude", - "longitude" - ], - "title": "GeoCoordinates", - "type": "object" - }, - { - "properties": { - "@type": { - "default": "GeoShape", - "description": "A structured representation that describes the coordinates of a geographic feature.", - "title": "@Type", - "type": "string" - }, - "box": { - "description": "A box is a rectangular region defined by a pair of coordinates representing the southwest and northeast corners of the box.", - "title": "Box", - "type": "string" - } - }, - "required": [ - "box" - ], - "title": "GeoShape", - "type": "object" - } - ], - "description": "Specifies the geographic coordinates of the place in the form of a point location, line, or area coverage extent.", - "title": "Geo" - }, - "additionalProperty": { - "description": "Additional properties of the place.", - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "anyOf": [ - { + "name": { + "description": "The name of the property.", + "title": "Name", "type": "string" }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" }, - { - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - }, - "type": "array" + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" } + }, + "required": [ + "name", + "value" ], - "description": "The value of the property.", - "title": "Value" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" + "title": "Property Value", + "type": "object" }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" + { + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "type": "array" } - }, - "required": [ - "name", - "value" ], - "title": "Property Value", - "type": "object" + "description": "The value of the property.", + "title": "Value" }, - "title": "Additional properties", - "type": "array" - } + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" }, - "title": "Place", - "type": "object" + "title": "Additional properties", + "type": "array" } - ], - "description": "The spatial coverage of the media object.", - "title": "Spatial coverage" + }, + "title": "Spatial coverage", + "type": "object", + "description": "The spatial coverage of the media object." }, "temporalCoverage": { - "anyOf": [ - { - "properties": { - "startDate": { - "description": "A date/time object containing the instant corresponding to the commencement of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM).", - "format": "date-time", - "title": "Start date", - "type": "string" - }, - "endDate": { - "description": "A date/time object containing the instant corresponding to the termination of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM). If the ending date is left off, that means the temporal coverage is ongoing.", - "format": "date-time", - "title": "End date", - "type": "string" - } - }, - "required": [ - "startDate" - ], - "title": "TemporalCoverage", - "type": "object" + "properties": { + "startDate": { + "description": "A date/time object containing the instant corresponding to the commencement of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM).", + "format": "date-time", + "title": "Start date", + "type": "string" + }, + "endDate": { + "description": "A date/time object containing the instant corresponding to the termination of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM). If the ending date is left off, that means the temporal coverage is ongoing.", + "format": "date-time", + "title": "End date", + "type": "string" } + }, + "required": [ + "startDate" ], - "description": "The temporal coverage of the media object.", - "title": "Temporal coverage" + "title": "Temporal coverage", + "type": "object", + "description": "The temporal coverage of the media object." }, "sourceOrganization": { - "anyOf": [ - { - "properties": { - "@type": { - "const": "Organization", - "default": "Organization", - "title": "@Type", - "type": "string" - }, - "name": { - "description": "Name of the organization that created the media object.", - "title": "Name", - "type": "string" - }, - "url": { - "anyOf": [ - { - "format": "uri", - "maxLength": 2083, - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "A URL to the homepage for the organization.", - "title": "URL" - }, - "address": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Full address for the organization - e.g., \u201c8200 Old Main Hill, Logan, UT 84322-8200\u201d.", - "title": "Address" - } + "properties": { + "@type": { + "const": "Organization", + "default": "Organization", + "title": "@Type", + "type": "string" + }, + "name": { + "description": "Name of the organization that created the media object.", + "title": "Name", + "type": "string" + }, + "url": { + "description": "A URL to the homepage for the organization.", + "errorMessage": { + "pattern": "must match format \"url\"" }, - "required": [ - "name" - ], - "title": "Media Object Source Organization", - "type": "object" + "maxLength": 2083, + "minLength": 1, + "pattern": "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$", + "title": "URL", + "type": "string" + }, + "address": { + "description": "Full address for the organization - e.g., \u201c8200 Old Main Hill, Logan, UT 84322-8200\u201d.", + "title": "Address", + "type": "string" } + }, + "required": [ + "name" ], - "description": "The organization that provided the media object.", - "title": "Source organization" + "title": "Source organization", + "type": "object", + "description": "The organization that provided the media object." } }, "required": [ @@ -1149,33 +1113,20 @@ "type": "string" }, "url": { - "anyOf": [ - { - "format": "uri", - "maxLength": 2083, - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, "description": "A URL to the homepage for the organization.", - "title": "URL" + "errorMessage": { + "pattern": "must match format \"url\"" + }, + "maxLength": 2083, + "minLength": 1, + "pattern": "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$", + "title": "URL", + "type": "string" }, "address": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, "description": "Full address for the organization - e.g., \u201c8200 Old Main Hill, Logan, UT 84322-8200\u201d.", - "title": "Address" + "title": "Address", + "type": "string" } }, "required": [ @@ -2865,31 +2816,200 @@ "errorMessage": { "pattern": "must match format \"url\"" }, - "maxLength": 2083, - "minLength": 1, - "pattern": "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$", - "title": "Content URL", - "type": "string" - }, - "encodingFormat": { - "description": "Represents the specific file format in which the media is encoded.", - "title": "Encoding format", - "type": "string" - }, - "contentSize": { - "description": "Represents the file size, expressed in bytes, kilobytes, megabytes, or another unit of measurement.", - "title": "Content size", - "type": "string" + "maxLength": 2083, + "minLength": 1, + "pattern": "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$", + "title": "Content URL", + "type": "string" + }, + "encodingFormat": { + "description": "Represents the specific file format in which the media is encoded.", + "title": "Encoding format", + "type": "string" + }, + "contentSize": { + "description": "Represents the file size, expressed in bytes, kilobytes, megabytes, or another unit of measurement.", + "title": "Content size", + "type": "string" + }, + "name": { + "description": "The name of the media object (file).", + "title": "Name", + "type": "string" + }, + "additionalProperty": { + "description": "Additional properties of the media object.", + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + { + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "type": "array" + } + ], + "description": "The value of the property.", + "title": "Value" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "title": "Additional properties", + "type": "array" }, - "name": { - "description": "The name of the media object (file).", - "title": "Name", - "type": "string" - }, - "additionalProperty": { - "anyOf": [ - { - "items": { + "variableMeasured": { + "description": "Measured variables.", + "items": { + "anyOf": [ + { + "type": "string" + }, + { "properties": { "@type": { "default": "PropertyValue", @@ -3048,510 +3168,305 @@ ], "title": "Property Value", "type": "object" - }, - "type": "array" - } - ], - "description": "Additional properties of the media object.", - "title": "Additional properties" - }, - "variableMeasured": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "anyOf": [ - { - "type": "string" - }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - }, - { - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - }, - "type": "array" - } - ], - "description": "The value of the property.", - "title": "Value" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - } - ] - }, - "type": "array" - } - ], - "description": "Measured variables.", - "title": "Variables measured" + } + ] + }, + "title": "Variables measured", + "type": "array" }, "spatialCoverage": { - "anyOf": [ - { - "properties": { - "@type": { - "default": "Place", - "description": "Represents the focus area of the record's content.", - "title": "@Type", - "type": "string" - }, - "name": { - "description": "Name of the place.", - "title": "Name", - "type": "string" - }, - "geo": { - "anyOf": [ - { - "properties": { - "@type": { - "default": "GeoCoordinates", - "description": "Geographic coordinates that represent a specific location on the Earth's surface. GeoCoordinates typically consists of two components: latitude and longitude.", - "title": "@Type", - "type": "string" - }, - "latitude": { - "description": "Represents the angular distance of a location north or south of the equator, measured in degrees and ranges from -90 to +90 degrees.", - "title": "Latitude", - "type": "number" - }, - "longitude": { - "description": "Represents the angular distance of a location east or west of the Prime Meridian, measured in degrees and ranges from -180 to +180 degrees.", - "title": "Longitude", - "type": "number" - } - }, - "required": [ - "latitude", - "longitude" - ], - "title": "GeoCoordinates", - "type": "object" + "properties": { + "@type": { + "default": "Place", + "description": "Represents the focus area of the record's content.", + "title": "@Type", + "type": "string" + }, + "name": { + "description": "Name of the place.", + "title": "Name", + "type": "string" + }, + "geo": { + "anyOf": [ + { + "properties": { + "@type": { + "default": "GeoCoordinates", + "description": "Geographic coordinates that represent a specific location on the Earth's surface. GeoCoordinates typically consists of two components: latitude and longitude.", + "title": "@Type", + "type": "string" }, - { - "properties": { - "@type": { - "default": "GeoShape", - "description": "A structured representation that describes the coordinates of a geographic feature.", - "title": "@Type", - "type": "string" - }, - "box": { - "description": "A box is a rectangular region defined by a pair of coordinates representing the southwest and northeast corners of the box.", - "title": "Box", - "type": "string" - } - }, - "required": [ - "box" - ], - "title": "GeoShape", - "type": "object" + "latitude": { + "description": "Represents the angular distance of a location north or south of the equator, measured in degrees and ranges from -90 to +90 degrees.", + "title": "Latitude", + "type": "number" + }, + "longitude": { + "description": "Represents the angular distance of a location east or west of the Prime Meridian, measured in degrees and ranges from -180 to +180 degrees.", + "title": "Longitude", + "type": "number" } + }, + "required": [ + "latitude", + "longitude" ], - "description": "Specifies the geographic coordinates of the place in the form of a point location, line, or area coverage extent.", - "title": "Geo" + "title": "GeoCoordinates", + "type": "object" }, - "additionalProperty": { - "description": "Additional properties of the place.", - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", + { + "properties": { + "@type": { + "default": "GeoShape", + "description": "A structured representation that describes the coordinates of a geographic feature.", + "title": "@Type", + "type": "string" + }, + "box": { + "description": "A box is a rectangular region defined by a pair of coordinates representing the southwest and northeast corners of the box.", + "title": "Box", + "type": "string" + } + }, + "required": [ + "box" + ], + "title": "GeoShape", + "type": "object" + } + ], + "description": "Specifies the geographic coordinates of the place in the form of a point location, line, or area coverage extent.", + "title": "Geo" + }, + "additionalProperty": { + "description": "Additional properties of the place.", + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "anyOf": [ + { "type": "string" }, - "value": { - "anyOf": [ - { + { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", "type": "string" }, - { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" }, - { - "items": { - "properties": { - "@type": { - "default": "PropertyValue", - "description": "A property-value pair.", - "title": "@Type", - "type": "string" - }, - "propertyID": { - "description": "The ID of the property.", - "title": "Property ID", - "type": "string" - }, - "name": { - "description": "The name of the property.", - "title": "Name", - "type": "string" - }, - "value": { - "description": "The value of the property.", - "title": "Value", - "type": "string" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" - }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" - } - }, - "required": [ - "name", - "value" - ], - "title": "Property Value", - "type": "object" - }, - "type": "array" + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" } + }, + "required": [ + "name", + "value" ], - "description": "The value of the property.", - "title": "Value" - }, - "unitCode": { - "description": "The unit of measurement for the value.", - "title": "Measurement unit", - "type": "string" - }, - "description": { - "description": "A description of the property.", - "title": "Description", - "type": "string" - }, - "minValue": { - "description": "The minimum allowed value for the property.", - "title": "Minimum value", - "type": "number" + "title": "Property Value", + "type": "object" }, - "maxValue": { - "description": "The maximum allowed value for the property.", - "title": "Maximum value", - "type": "number" + { + "items": { + "properties": { + "@type": { + "default": "PropertyValue", + "description": "A property-value pair.", + "title": "@Type", + "type": "string" + }, + "propertyID": { + "description": "The ID of the property.", + "title": "Property ID", + "type": "string" + }, + "name": { + "description": "The name of the property.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "The value of the property.", + "title": "Value", + "type": "string" + }, + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" + }, + "type": "array" } - }, - "required": [ - "name", - "value" ], - "title": "Property Value", - "type": "object" + "description": "The value of the property.", + "title": "Value" }, - "title": "Additional properties", - "type": "array" - } + "unitCode": { + "description": "The unit of measurement for the value.", + "title": "Measurement unit", + "type": "string" + }, + "description": { + "description": "A description of the property.", + "title": "Description", + "type": "string" + }, + "minValue": { + "description": "The minimum allowed value for the property.", + "title": "Minimum value", + "type": "number" + }, + "maxValue": { + "description": "The maximum allowed value for the property.", + "title": "Maximum value", + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "title": "Property Value", + "type": "object" }, - "title": "Place", - "type": "object" + "title": "Additional properties", + "type": "array" } - ], - "description": "The spatial coverage of the media object.", - "title": "Spatial coverage" + }, + "title": "Spatial coverage", + "type": "object", + "description": "The spatial coverage of the media object." }, "temporalCoverage": { - "anyOf": [ - { - "properties": { - "startDate": { - "description": "A date/time object containing the instant corresponding to the commencement of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM).", - "format": "date-time", - "title": "Start date", - "type": "string" - }, - "endDate": { - "description": "A date/time object containing the instant corresponding to the termination of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM). If the ending date is left off, that means the temporal coverage is ongoing.", - "format": "date-time", - "title": "End date", - "type": "string" - } - }, - "required": [ - "startDate" - ], - "title": "TemporalCoverage", - "type": "object" + "properties": { + "startDate": { + "description": "A date/time object containing the instant corresponding to the commencement of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM).", + "format": "date-time", + "title": "Start date", + "type": "string" + }, + "endDate": { + "description": "A date/time object containing the instant corresponding to the termination of the time interval (ISO8601 formatted date - YYYY-MM-DDTHH:MM). If the ending date is left off, that means the temporal coverage is ongoing.", + "format": "date-time", + "title": "End date", + "type": "string" } + }, + "required": [ + "startDate" ], - "description": "The temporal coverage of the media object.", - "title": "Temporal coverage" + "title": "Temporal coverage", + "type": "object", + "description": "The temporal coverage of the media object." }, "sourceOrganization": { - "anyOf": [ - { - "properties": { - "@type": { - "const": "Organization", - "default": "Organization", - "title": "@Type", - "type": "string" - }, - "name": { - "description": "Name of the organization that created the media object.", - "title": "Name", - "type": "string" - }, - "url": { - "anyOf": [ - { - "format": "uri", - "maxLength": 2083, - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "A URL to the homepage for the organization.", - "title": "URL" - }, - "address": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Full address for the organization - e.g., \u201c8200 Old Main Hill, Logan, UT 84322-8200\u201d.", - "title": "Address" - } + "properties": { + "@type": { + "const": "Organization", + "default": "Organization", + "title": "@Type", + "type": "string" + }, + "name": { + "description": "Name of the organization that created the media object.", + "title": "Name", + "type": "string" + }, + "url": { + "description": "A URL to the homepage for the organization.", + "errorMessage": { + "pattern": "must match format \"url\"" }, - "required": [ - "name" - ], - "title": "Media Object Source Organization", - "type": "object" + "maxLength": 2083, + "minLength": 1, + "pattern": "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$", + "title": "URL", + "type": "string" + }, + "address": { + "description": "Full address for the organization - e.g., \u201c8200 Old Main Hill, Logan, UT 84322-8200\u201d.", + "title": "Address", + "type": "string" } + }, + "required": [ + "name" ], - "description": "The organization that provided the media object.", - "title": "Source organization" + "title": "Source organization", + "type": "object", + "description": "The organization that provided the media object." } }, "required": [