0

There are many examples of how to use $ id and $ ref within the same Json schema file. But I have not found any example of how to use it with multiple schema files. I am with a Spring Boot project and mongoDB. I have my Schema files in the path:

/resources/schemas/
             root_schema.json
             centros_schema.json

the root_schema.json is an array of buildings (centros), and the centros_schema.json is where I define how is a building (centro).

I have followed the documentation here. But I have not been able to make it work and link the $id in centros_shema.json with the $ref in root_schema. See if someone can tell me how I can do it.

this is my root_schema.json:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "centros": {
            "type": "array",
            "items": [
                {
                    "$ref": "centros_schema.json"
                }
            ]
        }
    },
    "required": [
        "centros"
    ]
}

and this is my centros_schema.json:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "centros_schema.json",
    "type": "object",
    "properties": {
        "uid": {
            "type": "string"
        },
        "nombre": {
            "type": "string"
        },
        "tipo": {
            "type": "string"
        },
        "direccion": {
            "type": "object",
            "properties": {
                "calle": {
                    "type": "string"
                },
                "codigoPostal": {
                    "type": "string"
                },
                "municipio": {
                    "type": "string"
                },
                "provincia": {
                    "type": "string"
                },
                "ubicacion": {
                    "type": "object",
                    "properties": {
                        "latitud": {
                            "type": "string"
                        },
                        "longitud": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "latitud",
                        "longitud"
                    ]
                }
            },
            "required": [
                "calle",
                "codigoPostal",
                "municipio",
                "provincia",
                "ubicacion"
            ]
        },
        "horario": {
            "type": "object",
            "properties": {
                "apertura": {
                    "type": "string"
                },
                "cierre": {
                    "type": "string"
                }
            },
            "required": [
                "apertura",
                "cierre"
            ]
        },
        "dispositivos": {
            "type": "array",
            "items": [
                {
                    "type": "object",
                    "properties": {
                        "uid": {
                            "type": "string"
                        },
                        "descripcion": {
                            "type": "string"
                        },
                        "tipo": {
                            "type": "string"
                        },
                        "adquisicion": {
                            "type": "string"
                        },
                        "sensores": {
                            "type": "array",
                            "items": [
                                {
                                    "type": "object",
                                    "properties": {
                                        "variable": {
                                            "type": "string"
                                        },
                                        "unidad": {
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "variable",
                                        "unidad"
                                    ]
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "variable": {
                                            "type": "string"
                                        },
                                        "unidad": {
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "variable",
                                        "unidad"
                                    ]
                                }
                            ]
                        }
                    },
                    "required": [
                        "uid",
                        "descripcion",
                        "tipo",
                        "adquisicion",
                        "sensores"
                    ]
                },
                {
                    "type": "object",
                    "properties": {
                        "uid": {
                            "type": "string"
                        },
                        "descripcion": {
                            "type": "string"
                        },
                        "tipo": {
                            "type": "string"
                        },
                        "adquisicion": {
                            "type": "string"
                        },
                        "sensores": {
                            "type": "array",
                            "items": [
                                {
                                    "type": "object",
                                    "properties": {
                                        "variable": {
                                            "type": "string"
                                        },
                                        "unidad": {
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "variable",
                                        "unidad"
                                    ]
                                }
                            ]
                        }
                    },
                    "required": [
                        "uid",
                        "descripcion",
                        "tipo",
                        "adquisicion",
                        "sensores"
                    ]
                }
            ]
        }
    },
    "required": [
        "uid",
        "nombre",
        "tipo",
        "direccion",
        "horario",
        "dispositivos"
    ]
}

Updated

This is the error it throws at me. it doesn't matter which routes i use.

2021-05-24 21:34:54.140[0;39m [31mERROR[0;39m [35m4304[0;39m [2m---[0;39m [2m[nio-9000-exec-2][0;39m [36mo.a.c.c.C.[.[.[/].[dispatcherServlet]   [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.networknt.schema.JsonSchemaException: java.io.FileNotFoundException: \centros_schema.json (El sistema no puede encontrar el archivo especificado)] with root cause

java.io.FileNotFoundException: \centros_schema.json (El sistema no puede encontrar el archivo especificado)
    at java.io.FileInputStream.open0(Native Method) ~[na:1.8.0_291]
    at java.io.FileInputStream.open(Unknown Source) ~[na:1.8.0_291]
    at java.io.FileInputStream.<init>(Unknown Source) ~[na:1.8.0_291]
    at java.io.FileInputStream.<init>(Unknown Source) ~[na:1.8.0_291]
    at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source) ~[na:1.8.0_291]
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown Source) ~[na:1.8.0_291]
    at com.networknt.schema.uri.URLFetcher.openConnectionCheckRedirects(URLFetcher.java:57) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.uri.URLFetcher.fetch(URLFetcher.java:43) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.uri.URISchemeFetcher.fetch(URISchemeFetcher.java:50) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:337) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.RefValidator.getRefSchema(RefValidator.java:83) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.RefValidator.<init>(RefValidator.java:46) ~[json-schema-validator-1.0.52.jar:na]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_291]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_291]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_291]
    at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:1.8.0_291]
    at com.networknt.schema.ValidatorTypeCode.newValidator(ValidatorTypeCode.java:131) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonMetaSchema.newValidator(JsonMetaSchema.java:351) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ValidationContext.newValidator(ValidationContext.java:57) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.read(JsonSchema.java:217) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.getValidators(JsonSchema.java:406) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:239) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ItemsValidator.doValidate(ItemsValidator.java:99) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ItemsValidator.validate(ItemsValidator.java:80) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:241) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.PropertiesValidator.validate(PropertiesValidator.java:70) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:241) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.BaseJsonValidator.validate(BaseJsonValidator.java:103) ~[json-schema-validator-1.0.52.jar:na]
    at com.envira.gijonin.centros.utils.Utils.validateJsonUsingSchema(Utils.java:31) ~[classes/:na]
    at com.envira.gijonin.centros.centros.CentrosController.postCentros(CentrosController.java:83) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_291]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_291]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_291]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_291]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_291]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_291]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_291]

Update 2

when i use "$ref": "centros_schema.json" it seems to find the file, but now it throws me the following error:

[2m2021-05-24 21:45:14.175[0;39m [31mERROR[0;39m [35m4304[0;39m [2m---[0;39m [2m[nio-9000-exec-8][0;39m [36mo.a.c.c.C.[.[.[/].[dispatcherServlet]   [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.networknt.schema.JsonSchemaException: #/properties/centros/items/$ref: Reference centros_schema.json cannot be resolved] with root cause

com.networknt.schema.JsonSchemaException: #/properties/centros/items/$ref: Reference centros_schema.json cannot be resolved
    at com.networknt.schema.RefValidator.<init>(RefValidator.java:50) ~[json-schema-validator-1.0.52.jar:na]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_291]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_291]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_291]
    at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:1.8.0_291]
    at com.networknt.schema.ValidatorTypeCode.newValidator(ValidatorTypeCode.java:131) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonMetaSchema.newValidator(JsonMetaSchema.java:351) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ValidationContext.newValidator(ValidationContext.java:57) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.read(JsonSchema.java:217) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.getValidators(JsonSchema.java:406) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:239) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ItemsValidator.doValidate(ItemsValidator.java:99) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.ItemsValidator.validate(ItemsValidator.java:80) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:241) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.PropertiesValidator.validate(PropertiesValidator.java:70) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:241) ~[json-schema-validator-1.0.52.jar:na]
    at com.networknt.schema.BaseJsonValidator.validate(BaseJsonValidator.java:103) ~[json-schema-validator-1.0.52.jar:na]
    at com.envira.gijonin.centros.utils.Utils.validateJsonUsingSchema(Utils.java:31) ~[classes/:na]
    at com.envira.gijonin.centros.centros.CentrosController.postCentros(CentrosController.java:83) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_291]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_291]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_291]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_291]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.6.jar:5.3.6]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.6.jar:5.3.6]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_291]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_291]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.45.jar:9.0.45]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_291]
Vikitor
  • 73
  • 9

3 Answers3

2

I just solved it. There is one thing that I had not understood. I thought that the documentation of Json Schema and how to use it was the only thing to keep in mind since it was a "universal" cross-platform system. But it turns out that it is not the same for all libraries. I am using this dependency:

<dependency>
            <groupId>com.networknt</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>1.0.52</version>
        </dependency>

And it requires adding the word "classpath" or "resource" at the beginning of the uri. So what worked for me was to remove the $id and use $ref as follows:

"$ref": "classpath:/schemas/centros_schema.json"

Thank you very much for your help. It has been very useful.

Vikitor
  • 73
  • 9
1

JSON Schema $ref resolution uses the URI resolution process. Note, these are NOT URLs, and are not nessecerily relating to a location of any physical files, nor are they nessecerily network-addressable. $id is an identifier only.

The URI is not a network locator, only an identifier. A schema need not be downloadable from the address if it is a network-addressable
URL, and implementations SHOULD NOT assume they should perform a
network operation when they encounter a network-addressable URI.

https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.3

In practice this means that you have to load in your schemas to the implementation, so it knows which identifiers relate to which schema resources.

Some implementations may allow you to load in JSON files from a folder, and then using their $id values, determine URI resolution, but such features are implementation specific.

You would have to look at the documentation for the implementation you're using as to how to load in additional schemas.

Additionally, the URI used in your $ref is resolved against the base URI of the currently scoped schema resource. You should define an $id for your primary schema in order to provide a base URI. Think of it like anchor links in your browser. If a base URI can't be established from the schema resource, then one is determined by the implementation, as per URI resolution protocol.

The simplest and most straight forward referencing approach when you're learning is to always use full URIs for your reference.

If your $id in one schema is "$id": "http://ga4gh.org/schemas/discovery/search/definitions", then your $ref in another file might look like "$ref": "http://ga4gh.org/schemas/discovery/search/definitions#definitions/semver".

Relequestual
  • 11,631
  • 6
  • 47
  • 83
  • Thanks for answering. I had already read all that. But there must be something that I did not understand because when it comes to putting it into practice, it has not worked for me. The last thing I have tried and that complies with everything explained does not work either. This is what I have done. Based on what you have told me, an $id is not a route. just an identifier. So in "centers_schema.json" I have put "$id": "centers_schema", and in "root_schema.json" "$ ref": "centers_schema.json # centers_schema", but it has not worked. – Vikitor May 24 '21 at 16:17
  • also I have found this post that does not even declare an $id when using the $ref. Which raises the question of whether it is mandatory to use an $id. https://stackoverflow.com/questions/42999230/liquid-studio-how-to-write-a-json-schema-ref-to-another-file – Vikitor May 24 '21 at 16:31
  • "does not work" is vague, but you might have a bug in your particular evaluator implementation. If you add both schemas to the evaluator before evaluation, it should know that the second schema is addressable as "centros_schema.json" and therefore `$ref`s to it should work. – Ether May 24 '21 at 19:24
  • i just updated the post with the error message. i tried all imaginable path. none of them works. When i had 1 signle shcema, everything was working perfectly. – Vikitor May 24 '21 at 19:41
  • Vikitor, can you confirm you tried using fully qualified URIs? Including protocol and domain, for both `$id` and `$ref`? And can you confirm the implementation you're using allows you to load in additional schemas? Knowing what your implementation is might help here. – Relequestual May 25 '21 at 12:30
  • "...Which raises the question of whether it is mandatory to use an $id." - When `$id` is not defined, the base URI is determined by a process, which in the end sits with the implementation. The implementation may decide that `file://internal.internal` and resolve references using that base URI, and resolve the `file` protocol for references using local files in a specific folder. This is allowable. This is why I suggest using fully qualified URIs for `$id`. – Relequestual May 25 '21 at 12:36
  • i have tried with fully qualified names, relative, path, etc.. i also tried with $id + $ref and also only $ref. If you look at the data that I have put in the post, could you tell me what $ref should I put and what $id? Honestly, this system that the id is a route, without being a route, but also an identifier, seems very little intuitive to me. – Vikitor May 25 '21 at 14:33
  • I understand your frustration, but there are good reasons for it. The issue is usually not the $id and $ref values, but implementation configuration and useage. To confirm, you followed the "documentation" on how to do this as per https://github.com/networknt/json-schema-validator/blob/master/doc/schema-map.md ? – Relequestual May 25 '21 at 14:51
1

The documentation you linked to in your question is currently being rewritten and I think it will answer all of your questions on this topic. For now, here's an overview of how identifying and referencing schemas works.

Schemas are identified by non-relative URIs (https://example.com/path/to/schema or file:///path/to/schema). References ($ref) may be relative and resolve against the document's identifier to get a non-relative URI that identifies a schema.

If the identifier for your schema is file:///path/to/schemas/root_schema.json and the schema has a reference to centros_schema.json. The reference resolves to file:///path/to/schemas/centros_schema.json.

However, not all schemas have an identifier. If your schema doesn't have an identifier and you have a relative reference in your schema, that reference can't resolve to a non-relative URI to properly identify a schema. centros_schema.json can't resolve against because is not a non-relative URI. That's what the "reference can not be resolved" error you are getting is telling you.

One solution is to make your $ref a non-relative URI so it doesn't need an identifier to fully resolve.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "centros": {
            "type": "array",
            "items": [
                {
                    "$ref": "file:///path/to.schemas/centros_schema.json"
                }
            ]
        }
    },
    "required": [
        "centros"
    ]
}
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    ... no $id needed for centros_schema.json
}

This will work if the JSON Schema implementation you are using knows how to fetch file:// URIs from the file system. This appears to be the case, so I'll continue under that assumption.

The centros_schema.json schema doesn't need an $id because the non-relative URI used to reference it in root_schema.json becomes the identifier for the schema.

The other way to solve the problem is to assign an identifier for root_schema.json.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "file:///path/to/schema/root_schema.json",
    "type": "object",
    "properties": {
        "centros": {
            "type": "array",
            "items": [
                {
                    "$ref": "centros_schema.json"
                }
            ]
        }
    },
    "required": [
        "centros"
    ]
}
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    ... no $id needed for centros_schema.json
}

Now $ref can be relative and still resolve to a non-relative URI that identifies the centros_schema.json schema.

Of course, both of these solutions require that you hard-code file system paths into your schema, which can be problematic for a number of reasons. Ideally, the JSON Schema implementation will automatically assign an identifier using the file system path used to fetch root_schema.json in the first place. Then you can use file system relative paths and not have to assign $ids anywhere.

If the JSON Schema implementation doesn't support this, then you can use $id to assign https:// URIs to each schema and identify/reference them using those URIs.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "https://example.com/path/to/schemas/root_schema.json",
    "type": "object",
    "properties": {
        "centros": {
            "type": "array",
            "items": [
                {
                    "$ref": "centros_schema.json"
                }
            ]
        }
    },
    "required": [
        "centros"
    ]
}
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "https://example.com/path/to/schemas/centros_schema.json",
}

When using this method, you will need to preload both schemas into the JSON Schema implementation's internal database of schemas before attempting to validate an instance using your schemas. How this is done is implementation specific, so you'll have to check the documentation for the JSON Schema implementation you're using.

Jason Desrosiers
  • 22,479
  • 5
  • 47
  • 53