错误 |无法加载 json 架构! java.io.IOException:流关闭

ERROR | Failed to load json schema! java.io.IOException: Stream closed

我正在尝试根据其模式验证 json 对象,但我的模式文件非常大(386 行)。

这是我在 java 中的代码行:

public static void jsonSchemValidator() throws Exception {

        ObjectMapper objectMapper = new ObjectMapper();;


        InputStream jsonStream = inputStreamFromClasspath("/json/pickevent1.json");
        InputStream schemaStream = inputStreamFromClasspath("/json/schemaeg.json");

        JsonNode json = objectMapper.readTree(jsonStream);
        JsonNode jsonSchema = objectMapper.readTree(schemaStream);
        JsonSchemaFactory validatorFactory = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(jsonSchema));
        JsonSchema schema = validatorFactory.getSchema(schemaStream);
        Set<ValidationMessage> validationResult = schema.validate(json);
        if (validationResult.isEmpty()) {
            System.out.println("no validation errors :-)");
        } else {
            validationResult.forEach(vm -> System.out.println(vm.getMessage()));
        }
        jsonStream.close();
        schemaStream.close();
    }
}

IndputStream 的代码:

  public static InputStream inputStreamFromClasspath(String path) {
        return Utils.class.getResourceAsStream(path);
    }

以上适用于小型架构。但它给出了一个错误:

ERROR | Failed to load json schema!
java.io.IOException: Stream closed

这是堆栈跟踪:

ERROR | Failed to load json schema!
java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:336)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:539)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:133)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:256)
    at com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1655)
    at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1083)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3056)
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:315)
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:324)
    at common.Utils.jsonSchemValidator(Utils.java:105)
    at picking.begin.TestAssertionForPickBegin.before(TestAssertionForPickBegin.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:59)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:458)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:222)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:142)
    at org.testng.TestRunner.beforeRun(TestRunner.java:529)
    at org.testng.TestRunner.run(TestRunner.java:497)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
    at org.testng.TestNG.runSuites(TestNG.java:1049)
    at org.testng.TestNG.run(TestNG.java:1017)
    at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
    at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)
com.networknt.schema.JsonSchemaException: java.io.IOException: Stream closed
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:319)
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:324)
    at common.Utils.jsonSchemValidator(Utils.java:105)
    at picking.begin.TestAssertionForPickBegin.before(TestAssertionForPickBegin.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:59)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:458)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:222)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:142)
    at org.testng.TestRunner.beforeRun(TestRunner.java:529)
    at org.testng.TestRunner.run(TestRunner.java:497)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
    at org.testng.TestNG.runSuites(TestNG.java:1049)
    at org.testng.TestNG.run(TestNG.java:1017)
    at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
    at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)
Caused by: java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:336)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:539)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:133)
    at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:256)
    at com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1655)
    at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1083)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3056)
    at com.networknt.schema.JsonSchemaFactory.getSchema(JsonSchemaFactory.java:315)
    ... 26 more

我对 java 很陌生。任何建议都会有所帮助。谢谢。

我认为问题在于您从 InputStream schemaStream 读取了两次。

您先将其传递给 objectMapper.readTree(...),然后再将相同的 InputStream 传递给 validatorFactory.getSchema(...)

一般来说,这样做是一件坏事,因为第一次使用流可能会使它耗尽(即它没有更多数据到 return)或关闭,就像你的情况一样.老实说,我很惊讶您没有在小模式中得到类似的行为:我猜这是 InputStream 的一个怪癖,它从对 .getResourceAsStream(...) 的调用中得到 returned。

尝试从资源中打开一个新的 InputStream,而不是第二次尝试从其中读取。我还调整了您的代码以使用 try-with-resources,这样即使在抛出异常的情况下 InputStreams 也会关闭:

public static void jsonSchemValidator() throws Exception {

    ObjectMapper objectMapper = new ObjectMapper();

    try (InputStream jsonStream = inputStreamFromClasspath("/json/pickevent1.json")) {
        JsonNode json = objectMapper.readTree(jsonStream);
        JsonSchemaFactory validatorFactory;
        try (InputStream schemaStream = inputStreamFromClasspath("/json/schemaeg.json")) {
            JsonNode jsonSchema = objectMapper.readTree(schemaStream);
            validatorFactory = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(jsonSchema));
        }

        try (InputStream schemaStream = inputStreamFromClasspath("/json/schemaeg.json")) {
            JsonSchema schema = validatorFactory.getSchema(schemaStream);
            Set<ValidationMessage> validationResult = schema.validate(json);
            if (validationResult.isEmpty()) {
                System.out.println("no validation errors :-)");
            } else {
                validationResult.forEach(vm -> System.out.println(vm.getMessage()));
            }
        }
    }
}