[
https://issues.apache.org/jira/browse/UNOMI-571?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Kevan Jahanshahi updated UNOMI-571:
-----------------------------------
Attachment: form.contact.json
form.json
form.properties.json
> JSON Schema extension system
> ----------------------------
>
> Key: UNOMI-571
> URL: https://issues.apache.org/jira/browse/UNOMI-571
> Project: Apache Unomi
> Issue Type: New Feature
> Reporter: Kevan Jahanshahi
> Priority: Major
> Attachments: form.contact.json, form.json, form.properties.json
>
>
>
> h4. The goal here is to re-introduce the extension system we originally
> planned to implement to have a better integration with JSON Schema using the
> power of _[schema
> composition|https://json-schema.org/understanding-json-schema/reference/combining.html]_
> _(allOf{-}, anyOf, oneOf{-})_ keyword.
> The idea is:
> * to store extensions as full JSON schemas
> * update the original extended JSON schemas in RAM with *allOf* -OR *anyOf*
> OR *oneOf*- referencing the extensions (only one default cardinality will be
> handle at first: {*}allOf{*})
> h1. Why do we need extensions system for json schema ?
> because Unomi is going to close coimpletely the structure of events and
> incoming data for security purpose, any unknow property not mapped in a json
> schema will end up by rejecting the event.
> Due to this we are loosing the power of the events data structure that was
> free until Unomi 2.
> To counter this limitation we want the basic Object and schema provided by
> Unomi by default to be extensible so new properties and custom properties
> could still be used in events that would use Unomi based object.
> h1. Necessary changes, code and implem:
> h3. Create the extension it self:
> The extension that was a piece of JSON schema in first implem should now be a
> full JSON Schema definition that will only contains the new props to be
> validated on the same instance (object, event).
> impacts:
> * -remove the endpoints and custom storage of the JSON Schema extensions-
> *(Already done)*
> * use existing endpoints of JSON Schema to create them
> ** (we will probably have to introduce a new param or schema property to
> identify those schemas as extensions)
> h4. Before (first implem that have been reverted during the refacto):
> {code:java}
> {
> "id": "extension-test-event-1",
> "schemaId": "https://unomi.apache.org/schemas/json/events/test-event/1-0-0",
> "metadata": {
> "description": "Description of the extension",
> "id": "extension-test-event-1",
> "name": "The name of the extension"
> },
> "priority": "10",
> "extension": {
> "allOf": [
> {
> "$ref": "https://unomi.apache.org/schemas/json/customitem/1-0-0"
> }
> ],
> "properties": {
> "properties": {
> "properties": {
> "floatProperty": {
> "type": "number",
> "maximum": 100,
> "description": "Extension of float property"
> },
> "stringProperty": {
> "type": "string",
> "maxLength": 100,
> "description": "Updated description"
> },
> "newProperty": {
> "type": "string",
> "description": "A new element"
> }
> }
> }
> }
> }
> }
> {code}
> h4. After (expected implem):
> {code:java}
> {
> "$id":
> "https://unomi.apache.org/schemas/json/events/test-event-extension-1/1-0-0",
> "$schema": "https://json-schema.org/draft/2019-09/schema",
> "self": {
> "vendor": "org.apache.unomi",
> "name": "testEventExtension",
> "format": "jsonschema",
> "target": "events",
> "version": "1-0-0"
> },
> "title": "TestEventExtension1",
> "type": "object",
> "allOf": [
> {
> "$ref": "https://unomi.apache.org/schemas/json/customitem/1-0-0"
> }
> ],
> "properties": {
> "properties": {
> "properties": {
> "floatProperty": {
> "type": "number",
> "maximum": 100,
> "description": "Extension of float property"
> },
> "stringProperty": {
> "type": "string",
> "maxLength": 100,
> "description": "Updated description"
> },
> "newProperty": {
> "type": "string",
> "description": "A new element"
> }
> }
> }
> }
> }
> {code}
> * Some additional informations may be required on JSON Schema that are
> extensions, like:
> ** {*}-priority-{*}: NOT necessary anymore, there is no notion of priority
> in the allOf, anyOf, oneOf
> ** {-}*cardinality*{-}: NOT necessary in current implem, only "{*}allOf{*}"
> will be used and by default. (we will see if it's needed in next steps)
> ** {*}originalSchemaID{*}: the id of the original schema to extend.
> ** This infos may be store in the self part of the JSON Schema that will be
> extension (final structure could be discussed with the other dev of the
> team), here is an example:
>
> {code:java}
> "self": {
> "vendor": "org.apache.unomi",
> "name": "testEventExtension",
> "format": "jsonschema",
> "target": "events",
> "version": "1-0-0",
> "unomiExtends": {
> "schema": "https://unomi.apache.org/schemas/json/events/test-event/1-0-0"
> }
> }
> {code}
>
> h3. The merge:
> The merge was originally design to merge both the original JSON shema and the
> extension schema in a final JSON schema merged and stored in RAM.
> This was a bit complex to implement and could be handle in a more easy and
> fashioned way using the allOf, anyOf capabilities.
> Now that that the extensions are. real schemas we can just reference them
> using this notation (reusing above exemple)
> h4. original JSON Schema to be extended:
> {code:java}
> {
> "$id": "https://unomi.apache.org/schemas/json/events/test-event/1-0-0",
> "$schema": "https://json-schema.org/draft/2019-09/schema",
> "self": {
> "vendor": "org.apache.unomi",
> "name": "testEventForExtension",
> "format": "jsonschema",
> "target": "events",
> "version": "1-0-0"
> },
> "title": "TestEvent",
> "type": "object",
> "allOf": [
> {
> "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
> }
> ],
> "properties": {
> "properties": {
> "type": "object",
> "properties": {
> "floatProperty": {
> "type": "number"
> },
> "stringProperty": {
> "type": "string",
> "maxLength": 50,
> "description": "Initial description"
> }
> }
> }
> }
> }{code}
> h4. Original JSON Schema extended:
> {code:java}
> {
> "$id": "https://unomi.apache.org/schemas/json/events/test-event/1-0-0",
> "$schema": "https://json-schema.org/draft/2019-09/schema",
> "self": {
> "vendor": "org.apache.unomi",
> "name": "testEventForExtension",
> "format": "jsonschema",
> "target": "events",
> "version": "1-0-0"
> },
> "title": "TestEvent",
> "type": "object",
> "allOf": [
> {
> "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
> },
> {
> "$ref":
> "https://unomi.apache.org/schemas/json/events/test-event-extension-1/1-0-0"
> }
> ],
> "properties": {
> "properties": {
> "type": "object",
> "properties": {
> "floatProperty": {
> "type": "number"
> },
> "stringProperty": {
> "type": "string",
> "maxLength": 50,
> "description": "Initial description"
> }
> }
> }
> }
> }
> {code}
> As you can see we still need a merge operation that will store the results in
> RAM, but the only part to update in the original schema is the "{*}allOf{*}"
> property, by adding the extension schema URIs.
> h3. Changes on the original schema:
> In first implem we wanted to use the {*}additionalProperties: false{*}. but
> this is not possible because this keyword doesn't work with allOf, anyOf or
> other sub schemas combination.
> So we will have to use: *unevaluatedProperties: false* insteads.
> Read:
> *
> [https://json-schema.org/understanding-json-schema/reference/object.html#unevaluated-properties]
> *
> [https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties]
> NOTE that *unevaluatedProperties: false* should only be set on all our
> original schemas.
> Also we have to consider refactoring all our original schemas to avoid having
> nested objects in schemas.
> I attached 3 schemas to the ticket as an example of schema and extension for
> the form event.
> [form.json{^}!https://jira.jahia.org/images/icons/link_attachment_7.gif|width=7,height=7,align=absmiddle!{^}|https://jira.jahia.org/secure/attachment/48994/48994_form.json]is
> the Original JSON Schema for the form event it self
> [form.properties.json{^}!https://jira.jahia.org/images/icons/link_attachment_7.gif|width=7,height=7,align=absmiddle!{^}|https://jira.jahia.org/secure/attachment/48995/48995_form.properties.json]is
> the Original JSON Schema for the form properties
> [form.contact.json{^}!https://jira.jahia.org/images/icons/link_attachment_7.gif|width=7,height=7,align=absmiddle!{^}|https://jira.jahia.org/secure/attachment/48993/48993_form.contact.json]is
> the extension for a given form, providing fields for a contact form and
> extending the
> [form.properties.json{^}!https://jira.jahia.org/images/icons/link_attachment_7.gif|width=7,height=7,align=absmiddle!{^}|https://jira.jahia.org/secure/attachment/48995/48995_form.properties.json]schema.
> This does represent the final structure goal of schemas and extensions.
--
This message was sent by Atlassian Jira
(v8.20.7#820007)