0

Hibernate3 を使用した次のコードがあります。

List queryResult = session.createQuery("SELECT A, B from A, B where A.id = B.id");
for (Object o: queryResult) {
     Object[] array = (Objec[]) o;
     A a = (A) array[0];
     B b = (B) array[1];
     //do work
}

休止状態のクエリ結果を直接操作しているため、これは正常に機能します。ただし、後で使用できるように、queryResult を文字列にシリアル化する必要もあります。Jackson の json ライブラリを使用して、次のことを試しました。

ObjectMapper m = new ObjectMapper()
final String queryResultString = m.writeValueAsString(queryResult);

その後、Json から文字列を読み取って逆シリアル化し、Hibernate クエリの結果に戻そうとしましたが、そのときに問題が発生しました。読み取りコード:

List r = m.readValue(queryResultString, List.class);
for (Object o: r) {
     Object[] array = (Objec[]) o;
     A a = (A) array[0];
     B b = (B) array[1];
     //do work
}

Object[] のキャストは、ArrayList をオブジェクト配列にキャストできないと不平を言っています。

jackson hibernate モジュールを使用しようとしましたが、それも役に立ちませんでした。私の質問は次のとおりです。a) JSON シリアライゼーションでこれを行う正しい方法は何ですか? b) Jackson がそれを arraylist にデシリアライズするのはなぜですか?

4

1 に答える 1

0

予測

jackson でシリアライズすると、リストは [[A_item, B_item], [A_item2, B_item2], ... [A_itemn, B_itemn]] のようになります。必要に応じて、リストのリストまたは配列の配列があるためです (2 番目のリストには、常に A と B の 2 つの要素が含まれます)。

問題

あなたのリストはタイプされていません。したがって、jackson は json ストリームをリストのリストにデシリアライズします。ジャクソンが配列構造に遭遇し、逆シリアル化するタイプがわからない場合、配列ではなくリストに逆シリアル化するためです。

解決

1)配列を使用する代わりにリストを使用します.jacksonはデフォルトで配列ではなくリストに逆シリアル化するためです(クラスキャスト例外があるのはそのためです)。

2) Java 5以降 (ジェネリックを使用できることを意味します) を使用している場合は、jackson TypeReference クラスを使用できます。

List listOfLists = mapper.readValue(queryResultString, new TypeReference<List<Object[]>>() {});

3) Jackson から Genson http://code.google.com/p/genson/に切り替えます。デフォルトでは、リストではなく配列に逆シリアル化されます。Genson には、jackson にはない優れた機能が他にもたくさんあります。Wiki http://code.google.com/p/genson/wiki/GettingStartedを参照してください。Genson にはJava 6+が必要です。

List r = new Genson().deserialize(queryResultString, List.class);
for (Object o: r) {
 Object[] array = (Objec[]) o;
    // it works!
    A a = (A) array[0];
 }

編集 forEach ループがあります。Java 6 以降であると結論付けてから、Genson に切り替えます;)

于 2012-08-25T23:32:29.227 に答える