0

受信ペイロードを独自のスキーマと照合するために、一般的な JSON スキーマ ライブラリであるjson-schema-validatorを使用しています。

以下は私の悲しみの要約です。

private final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
    private JsonSchema preparedSchema;
    public ReportByTeamCriteriaSchemaChecker(String schemaLocationPath) {
        try {
            JsonNode schemaNode = JsonLoader.fromPath(schemaLocationPath);
            this.preparedSchema = this.factory.getJsonSchema(schemaNode);
        } catch (ProcessingException | IOException e) {
            e.printStackTrace();
        }
    }

ここまでは問題ありません。指定した場所にスキーマ ファイルが見つかり、schemaNode が準備されます。

着信 JSONString (より明確にはペイロード) が与えられた場合、以前にロードしたスキーマに対してその正確性を確認する方法は次のとおりです。

private Try<ProcessingReport>  checkAgainstSchema(JsonSchema schema, String jsonifiedString) {

   Try<ProcessingReport> result =
      Try
      .of(() ->  JsonLoader.fromString(jsonifiedString))
      .mapTry( (jsonNode) -> schema.validate(jsonNode));

        return (result);
    }

この関数は、次のように呼び出されます。

Try<String> syntaxParsingresult =
     this.checkAgainstSchema(this.preparedSchema, jsonifiedString)
    .map(e -> extractErrorMessagesFromReport(e));

build.gradleファイルの関連部分:

sourceCompatibility = '1.9'
targetCompatibility = '1.9'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

if (!hasProperty('mainClass')) {
    //ext.mainClass = 'test.NewMain'
    mainClassName = "drivers.ReportServerEntryPoint"
}

repositories {
    mavenCentral()
    maven { url "http://maven.restlet.org" }
}
ext.restletVersion = "2.3.10"

// ........

 // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
    // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8'
    // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.8'
    // https://mvnrepository.com/artifact/commons-io/commons-io
    compile group: 'commons-io', name: 'commons-io', version: '2.6'
    compile(group: "com.github.java-json-tools", name: "json-schema-validator", version: "2.2.10")
    // https://mvnrepository.com/artifact/io.vavr/vavr
    compile group: 'io.vavr', name: 'vavr', version: '0.9.2'

IntelliJ IDEA 内から実行すると、これは完全に正常に機能します(すべてのテストケースを含む) 。ただし、JAR をビルドしてコマンド ラインから実行すると、非常に紛らわしい例外がスローされます。

ここに画像の説明を入力

JVM (ReportByTeamCriteriaSchemaChecker.java:59) によって攻撃的であることが判明したソース行は、前述の関数呼び出しに対応します。

schema.validate(jsonNode)

私は vavr を使用しているため、最初は vavr と json-schema-validator と Jackson が一緒にいるのが不快ではないかと疑っていましたが、vavr の Try を使用していなくても実行時に例外がスローされることを確認しました。

StackOverflow でこの会話を参照しましたが、ほとんど役に立ちません。

私はJDK 1.9を使用しています:

java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

JSON Validation に精通している誰かが、私を正しい方向に向けてくれますか?


更新

実験として、以下を依存関係に追加しました。

    dependencies {
      compile(group: "com.github.fge", name: "jackson-coreutils", version: "1.8");
    }

この場合、コマンド ラインから JAR を実行すると、エラー メッセージがまったく逆になります。

Caused by: java.lang.IncompatibleClassChangeError: Found interface com.github.fge.jsonschema.main.JsonSchema, but class was expected
    at com.oneHuddle.application.utility.schemaChecker.ReportByTeamCriteriaSchemaChecker.validateAgainstSchema(ReportByTeamCriteriaSchemaChecker.java:59)
    at com.oneHuddle.application.ReportByTeamResource.lambda$getDefaultTeamReport$0(ReportByTeamResource.java:60)
    at io.vavr.control.Either.flatMap(Either.java:331)
    at com.oneHuddle.application.ReportByTeamResource.getDefaultTeamReport(ReportByTeamResource.java:59)

どちらかといえば、私はもっと混乱しています!:-) IntelliJ 内からは問題なく実行できるのに、コマンド ラインから実行可能 JAR を実行するとこのエラーがスローされるのはなぜですか?

4

1 に答える 1

1

次のクラスに頼ることにより、

com.github.fge.jsonschema.main.JsonValidator

問題を回避することができました。

現在のコードは次のようになります。

private final JsonValidator validator = 
    JsonSchemaFactory.byDefault().getValidator();
private  JsonNode   schemaNode;
public ReportByTeamCriteriaSchemaChecker(String schemaLocationPath) {
    try {
        this.schemaNode = JsonLoader.fromPath(schemaLocationPath);
    } catch (IOException e) {
         e.printStackTrace();
    }
}

以前はスキーマを使用していた関数が、代わりにバリデーターを使用するようになりました。

private Try<ProcessingReport>  
validatePayload(
     JsonNode schemaNode, String payload) {

   Try<ProcessingReport> result =
      Try
      .of(()->  JsonLoader.fromString(payload))
      .mapTry((jsonNode)  ->  
             this.validator.validate(schemaNode,jsonNode));

   return (result);

}

制御関数は、前のアバターで行ったように動作します。

 public Either<Tuple2<Enum<ReportByTeamExecutionStatus>,String>,String>
    validateAgainstSchema(String jsonifiedString) {

       Try<String> syntaxParsingresult =
               this.validateAgainstSchema(this.schemaNode, jsonifiedString)
               .map(e -> extractErrorMessagesFromReport(e));
// ..... rest of the logic

以下を含む 3 ~ 4 の可能性を試しました。

  • すべての依存関係の強制更新
  • Gradleのスキャンレポートを作成する
  • Jackson と他の依存ライブラリのいくつかの異なるバージョンで遊んでいます

しかし、どれも機能しませんでしたが、これは機能しました。

明確にするために、IntelliJのランタイムクラスパスのビューとgradleコマンドの同じビューの正確な違いが何であるかを知りませんでした。明らかに、それらは微妙に (またはそれほど微妙ではない) 異なる方法で依存関係を解決します。でも、時間がありませんでした。

誰かに役立つ場合に備えて、ソリューションを投稿する必要があると思いました。

于 2018-12-21T10:57:30.007 に答える