如何使用包含对另一个模式的引用的模式验证 JSON?

How to validate JSON with schema which contains a reference to another schema?

我想用 JSON 模式文件验证 JSON 文件,该文件包含对另一个 JSON 模式文件的引用。

我加了一个JSON Schema Validator for my Apache Camel route. Because I use JSON schema version draft-07 and the default version is draft-04, I exposed a JsonSchemaLoader, see also .

第一个架构 test-schema-1 从 class 路径加载,但第二个 test-schema-2 从互联网加载。使用的 ID http://mycompany/test-schema2.json 只是一个 ID,不是真正的资源,因此我得到一个异常。

有没有办法从 class 路径加载第二个 JSON 模式?

Spring 启动应用程序

@SpringBootApplication
public class TestApplication {
  public static void main(String[] args) {
    SpringApplication.run(TestApplication.class, args);
  }

  @Bean
  public JsonSchemaLoader mySchemaLoader() {
    return (camelContext, schemaStream) -> 
        JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7).getSchema(schemaStream);
  }

  @Bean
  public EndpointRouteBuilder routeBuilder() {
    return new EndpointRouteBuilder() {
      @Override
      public void configure() throws Exception {
        from(file("d:/tmp/camel/"))
            .to(jsonValidator("/test/test-schema1.json").advanced().schemaLoader(mySchemaLoader())).stop();
      }
    };
  }
}

JSON 架构

test-schema-1:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "http://mycompany/test-schema1.json",
    "type": "object",
    "properties": {
        "obj": {
            "$ref": "test-schema2.json"
        }
    },
    "required": [
        "target"
    ]
}

test-schema-2:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "http://mycompany/test-schema2.json",
    "type": "object",
    "properties": {
        "value": {
            "type": "string"
        }
    }
}

日志

Message History (complete message history is disabled)
---------------------------------------------------------------------------------------------------------------------------------------
RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
[route1            ] [route1            ] [from[file://d:/tmp/camel/]                                                    ] [         5]
...
[route1            ] [to1               ] [json-validator:///test/test-schema1.json?hash=93f27f49                        ] [         0]

Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------

com.networknt.schema.JsonSchemaException: java.net.UnknownHostException: mycompany
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:348) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.RefValidator.getRefSchema(RefValidator.java:76) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.RefValidator.<init>(RefValidator.java:41) ~[json-schema-validator-1.0.43.jar:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
    at com.networknt.schema.ValidatorTypeCode.newValidator(ValidatorTypeCode.java:131) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonMetaSchema.newValidator(JsonMetaSchema.java:342) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.ValidationContext.newValidator(ValidationContext.java:53) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchema.read(JsonSchema.java:198) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchema.initialize(JsonSchema.java:76) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.PropertiesValidator.<init>(PropertiesValidator.java:36) ~[json-schema-validator-1.0.43.jar:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
    at com.networknt.schema.ValidatorTypeCode.newValidator(ValidatorTypeCode.java:131) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonMetaSchema.newValidator(JsonMetaSchema.java:342) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.ValidationContext.newValidator(ValidationContext.java:53) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchema.read(JsonSchema.java:198) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchema.initialize(JsonSchema.java:76) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchemaFactory.newJsonSchema(JsonSchemaFactory.java:254) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:296) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:304) ~[json-schema-validator-1.0.43.jar:na]
    at test.TestApplication.lambda[=14=](TestApplication.java:22) ~[classes/:na]
    at org.apache.camel.component.jsonvalidator.JsonValidatorEndpoint.getOrCreateSchema(JsonValidatorEndpoint.java:162) ~[camel-json-validator-3.5.0.jar:3.5.0]
    at org.apache.camel.component.jsonvalidator.JsonValidatorEndpoint.onExchange(JsonValidatorEndpoint.java:94) ~[camel-json-validator-3.5.0.jar:3.5.0]
    at org.apache.camel.support.ProcessorEndpoint.process(ProcessorEndpoint.java:61) ~[camel-support-3.5.0.jar:3.5.0]
    at org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:66) ~[camel-support-3.5.0.jar:3.5.0]
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:169) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:404) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:287) ~[camel-base-3.5.0.jar:3.5.0]
    at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:483) ~[camel-file-3.5.0.jar:3.5.0]
    at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:237) ~[camel-file-3.5.0.jar:3.5.0]
    at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:198) ~[camel-file-3.5.0.jar:3.5.0]
    at org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:190) ~[camel-support-3.5.0.jar:3.5.0]
    at org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:107) ~[camel-support-3.5.0.jar:3.5.0]
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[na:na]
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.net.UnknownHostException: mycompany
    at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:220) ~[na:na]
    at java.base/java.net.Socket.connect(Socket.java:608) ~[na:na]
    at java.base/java.net.Socket.connect(Socket.java:557) ~[na:na]
    at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:474) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:569) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:341) ~[na:na]
    at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:362) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1253) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1187) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1081) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1015) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1592) ~[na:na]
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520) ~[na:na]
    at com.networknt.schema.uri.URLFetcher.openConnectionCheckRedirects(URLFetcher.java:57) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.uri.URLFetcher.fetch(URLFetcher.java:43) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.uri.URISchemeFetcher.fetch(URISchemeFetcher.java:50) ~[json-schema-validator-1.0.43.jar:na]
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:325) ~[json-schema-validator-1.0.43.jar:na]
    ... 46 common frames omitted

URI 映射有一个配置 属性,请参阅 Configuration:

  • uriMappings

Map of public, typically internet-accessible schema URLs to alternate locations; this allows for offline validation of schemas that refer to public URLs. This is merged with any mappings the sonSchemaFactory may have been built.

The type for this variable is Map<String, String>.

修改后的代码:

@Bean
public JsonSchemaLoader mySchemaLoader() {

  final SchemaValidatorsConfig config = new SchemaValidatorsConfig();
  config.setUriMappings(
      Map.of("http://mycompany/test-schema2.json", "resource:/test/test-schema2.json"));

  return (camelContext, schemaStream) ->
      JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7).getSchema(schemaStream, config);
}