{ "cells": [ { "cell_type": "markdown", "id": "02d9a514", "metadata": {}, "source": [ "# NTV - JSON Schema extension to NTV data\n", "This Notebook contains the python implementation of the examples presented in the document (examples 1 to 6) as well as more complete examples (examples 7, 8 and 9).\n", "Functions `ntv_validate` and `ntv_validate_opt2` transpose the `validate` function of the `jsonschema` module to NTV data (file [ntv_schema.py](https://github.com/loco-philippe/NTV/blob/main/RFC/ntv_schema.py))" ] }, { "cell_type": "code", "execution_count": 1, "id": "570278ab", "metadata": { "scrolled": true }, "outputs": [], "source": [ "import pathlib\n", "import json_ntv\n", "from json_ntv.namespace import from_file\n", "from RFC.ntv_schema import ntv_validate, ntv_validate_opt2\n", "from json_ntv import Ntv\n", "from jsonschema import validate" ] }, { "cell_type": "markdown", "id": "e9834b7e", "metadata": {}, "source": [ "## Example 1 - NTV structure" ] }, { "cell_type": "code", "execution_count": 2, "id": "0f1e1085", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NtvList , , , [{\"family\": \"doe\"}, {\"childrens age\": [15, 24, 12]}] , \n", "NtvSingle , family , json , doe , /family\n", "NtvList , childrens age , , [15, 24, 12] , /childrens age\n", "NtvSingle , , json , 15 , /childrens age/0\n", "NtvSingle , , json , 24 , /childrens age/1\n", "NtvSingle , , json , 12 , /childrens age/2\n" ] } ], "source": [ "instance = {'family': 'doe', 'childrens age': [15, 24, 12] }\n", "ntv_instance = Ntv.obj(instance)\n", "\n", "for ntv in ntv_instance.tree:\n", " print (ntv.__class__.__name__, ', ', ntv.name, ', ', ntv.type_str, ', ', ntv.ntv_value, ', ', ntv.pointer())" ] }, { "cell_type": "markdown", "id": "c03a0f6d", "metadata": {}, "source": [ "## Example 2 - NTV instance" ] }, { "cell_type": "code", "execution_count": 3, "id": "c2a3f15d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " {'number1': [10, 20]}\n", " number1/1 - valueNtv : 20 {'minimum': 15}\n", " number1/0 - valueNtv : 10 {'maximum': 30}\n", " number1/1 - valueNtv : 20 {'maximum': 30}\n", " number1/0 - valueNtv : 10 {'maximum': 15}\n", "True\n", "\n", " {'number2': {'val1': 10, 'val2': 20}}\n", " number2/val2 - valueNtv : 20 {'minimum': 15}\n", " number2/val1 - valueNtv : 10 {'maximum': 30}\n", " number2/val2 - valueNtv : 20 {'maximum': 30}\n", " number2/val1 - valueNtv : 10 {'maximum': 15}\n", "True\n", "\n", " {'number3': [10, {'val2': 20}]}\n", " number3/1 - valueNtv : 20 {'minimum': 15}\n", " number3/0 - valueNtv : 10 {'maximum': 30}\n", " number3/1 - valueNtv : 20 {'maximum': 30}\n", " number3/0 - valueNtv : 10 {'maximum': 15}\n", "True\n" ] } ], "source": [ "instances = [ {'number1': [10, 20] },\n", " {'number2': {'val1': 10, 'val2': 20}},\n", " {'number3': [10, {'val2': 20}]}]\n", "\n", "schema = { 'properties': {'1': {'minimum': 15}},\n", " 'items': {'maximum': 30},\n", " 'prefixItems': [{'maximum': 15}]}\n", "\n", "for instance in instances:\n", " print ('\\n', instance)\n", " print(ntv_validate(instance, schema, mode=2))" ] }, { "cell_type": "markdown", "id": "384b602b", "metadata": {}, "source": [ "## Example 3 - NTVtype and NTVname" ] }, { "cell_type": "code", "execution_count": 4, "id": "e46517b6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " {'location': 'paris', 'dating:date': '2023-10-01'}\n", " /dating:date - valueNtv : 2023-10-01 {'typeNTV': {'enum': ['year', 'date', 'datetime']}}\n", " /location - valueNtv : paris {'nameNTV': {'maxLength': 10}}\n", " /dating:date - valueNtv : 2023-10-01 {'nameNTV': {'maxLength': 10}}\n", "True\n", "\n", " {'location': 'paris', 'dating:year': 2023}\n", " /dating:year - valueNtv : 2023 {'typeNTV': {'enum': ['year', 'date', 'datetime']}}\n", " /location - valueNtv : paris {'nameNTV': {'maxLength': 10}}\n", " /dating:year - valueNtv : 2023 {'nameNTV': {'maxLength': 10}}\n", "True\n" ] } ], "source": [ "instances = [ {'location': 'paris', 'dating:date': '2023-10-01'},\n", " {'location': 'paris', 'dating:year': 2023} ]\n", "\n", "schema = { 'properties': {\n", " 'dating': {'typeNTV': {'enum': ['year', 'date', 'datetime']}}},\n", " 'items': {\n", " 'nameNTV': {'maxLength': 10}}}\n", "\n", "for instance in instances:\n", " print ('\\n', instance)\n", " print(ntv_validate(instance, schema, mode=2))" ] }, { "cell_type": "markdown", "id": "a2e8b69c", "metadata": {}, "source": [ "## Example 4 - Extension NTV Schema - option 1" ] }, { "cell_type": "code", "execution_count": 5, "id": "5d606645", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " {'location': 'paris', 'dating:date': '2023-10-01'}\n", " /dating:date - typeNtv : date {'enum': ['year', 'date', 'datetime']}\n", " /location - nameNtv : location {'maxLength': 10}\n", " /dating:date - nameNtv : dating {'maxLength': 10}\n", "True\n", "\n", " {'location': 'paris', 'dating:year': 2023}\n", " /dating:year - typeNtv : year {'enum': ['year', 'date', 'datetime']}\n", " /location - nameNtv : location {'maxLength': 10}\n", " /dating:year - nameNtv : dating {'maxLength': 10}\n", "True\n" ] } ], "source": [ "instances = [ {'location': 'paris', 'dating:date': '2023-10-01'},\n", " {'location': 'paris', 'dating:year': 2023} ]\n", "\n", "schema = { 'dating': {\n", " ':typeNtv': {':enum': ['year', 'date', 'datetime'] }},\n", " ':items': {\n", " ':nameNtv': {':maxLength': 10}} }\n", "\n", "for instance in instances:\n", " print ('\\n', instance)\n", " print(ntv_validate_opt2(instance, schema, mode=2))" ] }, { "cell_type": "markdown", "id": "afd8121c", "metadata": {}, "source": [ "## Example 5 - Extension JSON Schema and NTV Schema - option 2" ] }, { "cell_type": "code", "execution_count": 6, "id": "42a80ba6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " {'location': 'paris', 'dating:date': '2023-10-01'}\n", " /dating:date - typeNtv : date {'enum': ['year', 'date', 'datetime']}\n", " /location - nameNtv : location {'maxLength': 10}\n", " /dating:date - nameNtv : dating {'maxLength': 10}\n", "True\n", "\n", " {'location': 'paris', 'dating:year': 2023}\n", " /dating:year - typeNtv : year {'enum': ['year', 'date', 'datetime']}\n", " /location - nameNtv : location {'maxLength': 10}\n", " /dating:year - nameNtv : dating {'maxLength': 10}\n", "True\n" ] } ], "source": [ "instances = [ {'location': 'paris', 'dating:date': '2023-10-01'},\n", " {'location': 'paris', 'dating:year': 2023}]\n", "\n", "schema = { '/dating': {\n", " 'typeNtv': {'enum': ['year', 'date', 'datetime']}},\n", " 'items': {\n", " 'nameNtv': {'maxLength': 10}}}\n", "\n", "for instance in instances:\n", " print ('\\n', instance)\n", " print(ntv_validate(instance, schema, mode=2))" ] }, { "cell_type": "markdown", "id": "61d125bd", "metadata": {}, "source": [ "## Example 6 - OpenAPI Schema" ] }, { "cell_type": "code", "execution_count": 7, "id": "d8b688a7", "metadata": {}, "outputs": [], "source": [ "import pathlib\n", "import json_ntv\n", "\n", "file = pathlib.Path(json_ntv.__file__).parent.parent / \"RFC\" / \"NTV_openAPI_namespace.ini\"\n", "from_file(file, '$openAPI.')" ] }, { "cell_type": "code", "execution_count": 8, "id": "63b8c467", "metadata": {}, "outputs": [], "source": [ "# example found in the OpenAPI documentation\n", "example_OAS = {\"servers\": [\n", " {\"url\": \"https://{username}.gigantic-server.com:{port}/{basePath}\",\n", " \"description\": \"The production API server\",\n", " \"variables\": {\n", " \"username\": {\n", " \"default\": \"demo\",\n", " \"description\": \"this value is assigned by the service provider, in this example `gigantic-server.com`\"},\n", " \"port\": {\n", " \"enum\": [\"8443\", \"443\"],\n", " \"default\": \"8443\"},\n", " \"basePath\": {\n", " \"default\": \"v2\"\n", " }}}]}" ] }, { "cell_type": "code", "execution_count": 9, "id": "b7c3f40f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\":$openAPI.servers.variables.default\": \"demo\"}\n", "{\":$openAPI.servers.variables.default\": \"demo\"}\n", "$openAPI.servers.variables.default\n" ] } ], "source": [ "# Example - with NTV types\n", "example_NTV = {\n", " \"example:$openAPI.\":\n", " {\"servers.\": [\n", " {\":url\": \"https://{username}.gigantic-server.com:{port}/{basePath}\",\n", " \":description\": \"The production API server\", \n", " \"variables.\": {\n", " \"username\": {\n", " \":default\": \"demo\",\n", " \":description\": \"this value is assigned by the service provider, in this example `gigantic-server.com`\"},\n", " \"port\": {\n", " \":enum\": [\"8443\", \"443\"],\n", " \"default\": \"8443\" },\n", " \"basePath\": {\n", " \":default\": \"v2\"}}}]}}\n", "schema_NTV = Ntv.obj(example_NTV)\n", "print(schema_NTV['#example:$openAPI./servers./0/variables./username/:default'])\n", "print(schema_NTV['#example/servers./0/variables./username/:default'])\n", "print(schema_NTV['#example/servers./0/variables./username/:default'].ntv_type)" ] }, { "cell_type": "code", "execution_count": 10, "id": "a086d0f8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\"user:$openAPI.servers.variables.default\": \"demo\"}\n", "{\"user:$openAPI.servers.variables.default\": \"demo\"}\n" ] } ], "source": [ "# Example - with comments\n", "schema_NTV2 = Ntv.obj(\n", " {\"example:$openAPI.servers.\" : { \n", " \"server1\": {\n", " \":url\": \"https://{username}.gigantic-server.com:{port}/{basePath}\",\n", " \"prod:description\": \"The production API server\", \n", " \"variables.\": {\n", " \"username\": {\n", " \"user:default\": \"demo\",\n", " \":description\": \"this value is assigned by the service provider, in this example `gigantic-server.com`\"},\n", " \"port\": {\n", " \":enum\": [\"8443\", \"443\"],\n", " \"default\": \"8443\" },\n", " \"basePath\": {\n", " \":default\": \"v2\"}}}}})\n", "print(schema_NTV2['#example:$openAPI.servers./server1/variables./username/user:default'])\n", "print(schema_NTV2['#example/server1/variables./username/user'])" ] }, { "cell_type": "markdown", "id": "1e96195d", "metadata": {}, "source": [ "## Example 7 - overview - JSON Schema" ] }, { "cell_type": "code", "execution_count": 11, "id": "590be1e0", "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Valid JSON object.\n", "NTV schema 1 - valid : True\n", "NTV schema 2 - valid : True\n" ] } ], "source": [ "data_product = {\n", " \"name\": \"Widget\",\n", " \"price\": 10.99,\n", " \"quantity\": 5 }\n", "\n", "json_schema = {\n", " \"title\": \"Product\",\n", " \"properties\": { \n", " \"name\": {\n", " \"type\": \"string\" },\n", " \"price\": {\n", " \"type\": \"number\", \n", " \"minimum\": 0 },\n", " \"quantity\": {\n", " \"type\": \"integer\", \n", " \"minimum\": 1 } },\n", " \"required\": [ \"name\", \"price\", \"quantity\"] }\n", "\n", "# example JSON Schema\n", "try:\n", " validate(data_product, json_schema)\n", " print(\"Valid JSON object.\")\n", "except Exception as e:\n", " print(\"Invalid JSON object:\", e)\n", " \n", "# example NTV Schema option 1\n", "schema_opt1 = {\n", " \"title\": \"Product\",\n", " \"/name\": {\n", " \"type\": \"string\" },\n", " \"/price\": {\n", " \"type\": \"number\", \n", " \"minimum\": 0 },\n", " \"/quantity\": {\n", " \"type\": \"integer\", \n", " \"minimum\": 1 } ,\n", " \"required\": [ \"/name\", \"/price\", \"/quantity\"] }\n", "print('NTV schema 1 - valid :', ntv_validate(data_product, schema_opt1))\n", "\n", "# example NTV Schema option 2\n", "schema = {\n", " \":title\": \"Product - NTVschema\",\n", " \"name\": {\n", " \":type\": \"string\" },\n", " \"price\": {\n", " \":type\": \"number\", \n", " \":minimum\": 0 },\n", " \"quantity\": {\n", " \":type\": \"integer\", \n", " \":minimum\": 1 },\n", " \":required\": [ \"name\", \"price\", \"quantity\"] }\n", "print('NTV schema 2 - valid :', ntv_validate_opt2(data_product, schema))" ] }, { "cell_type": "markdown", "id": "ab5c0f1b", "metadata": {}, "source": [ "## Example 8 - complete JSON Schema and NTV Schema" ] }, { "cell_type": "code", "execution_count": 12, "id": "8c47de8f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " /family - valueNtv : white {'maxLength': 10, 'type': ['string', 'integer']}\n", " /childrens/0 - valueNtv : 24 {'maximum': 25}\n", " /childrens/0 - nameNtv : {'maxLength': 10}\n", " /childrens/1 - valueNtv : 15 {'maximum': 25}\n", " /childrens/1 - nameNtv : {'maxLength': 10}\n", " /childrens/2 - valueNtv : None {'maximum': 25}\n", " /childrens/2 - nameNtv : walter jr {'maxLength': 10}\n", " /childrens/3 - valueNtv : 21 {'maximum': 23}\n", " /childrens/3 - valueNtv : 21 {'maximum': 25}\n", " /childrens/3 - nameNtv : judith {'maxLength': 10}\n", " /childrens - valueNtv : [24, 15, {\"walter jr\": null}, {\"judith\": 21}] {'maxItems': 4}\n", "\n", " True\n", " validate : \n", " validate : /family\n", " validate : /childrens\n", " validate : /childrens/0\n", " validate : /childrens/1\n", " validate : /childrens/2\n", " validate : /childrens/3\n", " validate : /childrens/1\n", " error /childrens/1 - valueNtv : 15 is not valid with schema : {'minimum': 16}\n", " validate : /childrens/3\n", " error /childrens/3 - valueNtv : 21 is not valid with schema : {'maximum': 20}\n", "\n", " False\n" ] } ], "source": [ "json_test = {'family' : 'white', \n", " 'childrens': [24, \n", " 15, \n", " {'walter jr': None}, \n", " {'judith': 21}]}\n", "\n", "json_schema = {'properties': {\n", " 'family':{\n", " 'maxLength':10,\n", " 'type': ['string', 'integer']},\n", " 'childrens':{\n", " 'maxItems': 4,\n", " 'items': {\n", " 'maximum': 25, \n", " 'propertyNames': {'maxLength':10},\n", " 'properties':{\n", " 'judith': {'maximum': 23}}}}}}\n", "\n", "validate(json_test, json_schema)\n", "print('\\n', ntv_validate(json_test, json_schema, mode=2))\n", "\n", "json_schema2 = {'properties': {\n", " 'family':{\n", " 'maxLength':10},\n", " 'childrens':{\n", " 'maxItems': 4,\n", " 'items': {\n", " 'maximum': 25, \n", " 'propertyNames': {'maxLength':10}},\n", " '/1': {'minimum':16},\n", " '/judith': {'maximum': 20}}}}\n", "\n", "validate(json_test, json_schema2)\n", "print('\\n', ntv_validate(json_test, json_schema2, mode=1))" ] }, { "cell_type": "markdown", "id": "fdc02124", "metadata": {}, "source": [ "## Example 9 - nested types - NTV Schema" ] }, { "cell_type": "code", "execution_count": 13, "id": "018361b8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " validate : example family:org.\n", " validate : example family:org./House.\n", " validate : example family:org./House./location:point\n", " validate : example family:org./House./arrival:year\n", " validate : example family:org./childrens:Person.\n", " validate : example family:org./childrens:Person./0\n", " validate : example family:org./childrens:Person./0\n", " validate : example family:org./childrens:Person./1\n", " validate : example family:org./childrens:Person./2\n", " validate : example family:org./childrens:Person./2/age\n", " validate : example family:org./pets\n", " validate : example family:org./pets/:$dog\n", " validate : example family:org./pets/:$dog\n", " validate : example family:org./pets/:$cat\n", " validate : example family:org./pets/:$mouse\n", " validate : example family:org./pets/:$mouse\n", "True\n", " validate : example family:org.\n", " validate : example family:org./House.\n", " validate : example family:org./House./location:point\n", " validate : example family:org./House./arrival:year\n", " validate : example family:org./childrens:Person.\n", " validate : example family:org./childrens:Person./0\n", " validate : example family:org./childrens:Person./0\n", " validate : example family:org./childrens:Person./1\n", " validate : example family:org./childrens:Person./2\n", " validate : example family:org./childrens:Person./2/age\n", " validate : example family:org./pets\n", " validate : example family:org./pets/:$dog\n", " validate : example family:org./pets/:$dog\n", " validate : example family:org./pets/:$cat\n", " validate : example family:org./pets/:$mouse\n", " validate : example family:org./pets/:$mouse\n", "True\n" ] } ], "source": [ "ntv_test2 = {\n", " 'example family::org.' : {\n", " 'name': 'white',\n", " 'House.':{\n", " 'location:point': [2.2, 48.5],\n", " ':Country.name': 'France',\n", " 'arrival:year': 2005},\n", " 'childrens:Person.': [ \n", " {'age': 21}, \n", " {':givenName': 'walter jr'}, \n", " {'age': 22, ':givenName': 'judith'}],\n", " 'pets::':{\n", " ':$dog': {'hector': 10}, \n", " ':$cat': {'tom': 5},\n", " ':$mouse': 3}}}\n", "\n", "ntv_schema3 = {\n", " 'properties': {\n", " 'House.': {\n", " 'properties':{\n", " 'location':{\n", " 'typeNtv': {'enum': ['point', 'geojson', 'org.Place.address']}},\n", " 'arrival': {\n", " 'typeNtv': {'enum': ['year', 'date', 'datetime']}}}},\n", " 'childrens':{ \n", " ':maxItems': 5,\n", " 'items': {\n", " 'properties':{\n", " 'age':{\n", " 'maximum': 25,\n", " 'typeNtv': {'enum': ['json', 'int']},\n", " }}}},\n", " 'pets':{\n", " 'prefixItems':[\n", " {'typeNtv': {'const':'$dog'}}],\n", " 'items':{\n", " 'typeNtv': {'enum': ['$dog', '$cat', '$mouse']}},\n", " 'properties': {\n", " ':$mouse': {'maximum': 10 }}}}}\n", "ntv_schema4 = { \n", " '/House.': {\n", " '/location':{\n", " 'typeNtv': {'enum': ['point', 'geojson', 'org.Place.address']}},\n", " '/arrival': {\n", " 'typeNtv': {'enum': ['year', 'date', 'datetime']}}},\n", " '/childrens':{ \n", " 'maxItems': 5,\n", " 'items': {\n", " '/age':{\n", " 'maximum': 25,\n", " 'typeNtv': {'enum': ['json', 'int']}}}},\n", " '/pets':{\n", " '/0':{ \n", " 'typeNtv': {'const':'$dog'}},\n", " 'items':{\n", " 'typeNtv': {'enum': ['$dog', '$cat', '$mouse']}}, \n", " '/:$mouse': {'maximum': 10 }}}\n", " \n", "print(ntv_validate(ntv_test2, ntv_schema3, mode=1))\n", "print(ntv_validate(ntv_test2, ntv_schema4, mode=1))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 5 }