2

JSON ファイルを解析する次のコードがあります。

@Override
Map<String, Configuration> parseJson() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each { schemaProtectionInformation ->
        processing(schemaProtectionInformation)
    }
}

private Object readConfigurationFile() {
    InputStream is = getClass().getClassLoader().getResourceAsStream("test.json")
    BufferedReader reader = new BufferedReader(new InputStreamReader(is))
    return new JsonSlurper().parse(reader)
}

次の JSON ファイルを処理するには:

{
  "schemas": [
    {
      "name": "plan_pm_test",
      "protectedDimensions": [
        {
          "name": "dActivityWbs",
          "usedToSecureFactTable": true,
          "aliasInFactTable": "PLAN_WBS",
          "levels" : ["LEVEL_1_ID","LEVEL_2_ID","LEVEL_3_ID","LEVEL_4_ID","LEVEL_5_ID","LEVEL_6_ID","LEVEL_7_ID","LEVEL_8_ID","LEVEL_9_ID"]
        },
        {
          "name": "dResponsibleOrganicUnit",
          "usedToSecureFactTable": true,
          "aliasInFactTable": "RES_ORG_UNIT",
          "levels" : ["ID","LEVEL_1_ID","LEVEL_2_ID"]
        },
        {
          "name": "dContributionOrganicUnit",
          "usedToSecureFactTable": true,
          "aliasInFactTable": "CON_ORG_UNIT",
          "levels" : ["ID","LEVEL_1_ID","LEVEL_2_ID"]
        }
      ]
    }
  ]
}

このコードを実行すると、次のエラーが表示されます。

Cannot cast object '[{name=plan_pm_test, protectedDimensions=[{aliasInFactTable=PLAN_WBS, levels=[LEVEL_1_ID, LEVEL_2_ID, LEVEL_3_ID, LEVEL_4_ID, LEVEL_5_ID, LEVEL_6_ID, LEVEL_7_ID, LEVEL_8_ID, LEVEL_9_ID], name=dActivityWbs, usedToSecureFactTable=true}, {aliasInFactTable=RES_ORG_UNIT, levels=[ID, LEVEL_1_ID, LEVEL_2_ID], name=dResponsibleOrganicUnit, usedToSecureFactTable=true}, {aliasInFactTable=CON_ORG_UNIT, levels=[ID, LEVEL_1_ID, LEVEL_2_ID], name=dContributionOrganicUnit, usedToSecureFactTable=true}]}]' with class 'java.util.ArrayList' to class 'java.util.Map' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.Map(groovy.json.internal.LazyMap)
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[{name=plan_pm_test, protectedDimensions=[{aliasInFactTable=PLAN_WBS, levels=[LEVEL_1_ID, LEVEL_2_ID, LEVEL_3_ID, LEVEL_4_ID, LEVEL_5_ID, LEVEL_6_ID, LEVEL_7_ID, LEVEL_8_ID, LEVEL_9_ID], name=dActivityWbs, usedToSecureFactTable=true}, {aliasInFactTable=RES_ORG_UNIT, levels=[ID, LEVEL_1_ID, LEVEL_2_ID], name=dResponsibleOrganicUnit, usedToSecureFactTable=true}, {aliasInFactTable=CON_ORG_UNIT, levels=[ID, LEVEL_1_ID, LEVEL_2_ID], name=dContributionOrganicUnit, usedToSecureFactTable=true}]}]' with class 'java.util.ArrayList' to class 'java.util.Map' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.Map(groovy.json.internal.LazyMap)
    at cern.ais.datawarehouse.baserver.mondriansecurity.common.schemaprotectionconfiguration.JsonResourceFileConfigurationRepositoryPopulator.readConfiguration(JsonResourceFileConfigurationRepositoryPopulator.groovy:23)
    at cern.ais.datawarehouse.baserver.mondriansecurity.common.schemaprotectionconfiguration.JsonResourceFileConfigurationRepositoryPopulatorTest.tes(JsonResourceFileConfigurationRepositoryPopulatorTest.groovy:12)

もちろん、アプリケーションのデバッグを段階的に開始して、コードのどの部分であるprocessing()がこの例外をスローするかを確認しました。驚くべきことに、そこにあるすべてのコードは正常に実行されます。例外をスローして結果を返すことはありません。

さらに驚いたのは、最初のメソッドのコードを少し変更すると、例外が発生せずに動作することです。

@Override
Map<String, Configuration> readConfiguration() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each { schemaProtectionInformation ->
        processing(schemaProtectionInformation)
    }
    println "test 2"
}

printlnメソッドがそこにあるものをどのように変更できるかわかりません。もちろん、トリックを実行するのは必ずしもprintlnメソッドである必要はありません。したがって、次のようなことをすると:

@Override
Map<String, Configuration> readConfiguration() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each { schemaProtectionInformation ->
        processing(schemaProtectionInformation)
    }
    test()
}

void test() {

}

同様に機能します(例外はスローされません)。json ファイルを処理した後に追加のコードを作成すると、ここで変更が必要になる理由がわかりません。

先ほど実際に処理メソッドをコメントアウトしたので、メソッド本体は以下のようになります。

@Override
Map<String, Configuration> readConfiguration() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each { schemaProtectionInformation ->
        //processing(schemaProtectionInformation)
    }
}

そして、私は同じ例外を受け取りますが。したがって、エラーは処理メソッドの実装とは関係ありません。

ご意見をお待ちしております。

4

2 に答える 2

1

Groovy では、returnは暗黙的であり、関数の最後のステートメントです。したがって、コードは次と同等です。

@Override
Map<String, Configuration> parseJson() {
    Object configurationFile = readConfigurationFile()
    return configurationFile.schemas.each { schemaProtectionInformation ->
        processing(schemaProtectionInformation)
    }
}

このeach関数は、呼び出された要素を返します。あなたの場合、schemas. ただし、スキーマはマップではなくコレクションです。ClassCastException が表示されます。あなたのコードは次と同等です:

@Override
Map<String, Configuration> parseJson() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each { schemaProtectionInformation ->
        processing(schemaProtectionInformation)
    }
    return configurationFile.schemas
}

このステートメントの後に何かを追加すると、別の暗黙的な が作成されるだけですreturn。明示的な を使用する必要がありますreturn configurationFile

于 2016-03-04T21:48:46.437 に答える
0

うわー、ごめんなさい。そんな初歩的なミス。このクラスの単体テストがなかったのは残念です。

明らかに欠けている部分は return キーワードです。現在のコードは次のようになります。

@Override
Map<String, Configuration> readConfiguration() {
    Object configurationFile = readConfigurationFile()
    configurationFile.schemas.each() { schemaProtectionInformation ->
        processSchemaDetailsFromFile(schemaProtectionInformation)
    }
    return schemasConfigurations
}

そして何の問題もなく動作します。

私の記憶が正しければ、このコードはreloadConfiguration()が値を返さないコードから進化したものです。次に、おそらく戻り値の型を変更しましたが、明示的な return ステートメントを追加するのを忘れていました。groovy では return キーワードを使用できないため、不平を言うことはなく、いくつかのリストを返そうとしましたが、失敗したため、このメソッドによって返される値の指定された型はマップでした。

うーん…寝不足のせい。

于 2016-03-04T21:48:29.677 に答える