3

私は小さなアプリに取り組んでおり、GWTを使用してそれを構築しています。JSONとして応答を返すリモートサーバーにリクエストを送信しようとしました。オーバーレイタイプの概念を使用してみましたが、機能しませんでした。私はコードを変更しているので、GoogleGWTチュートリアルが残っていた場所から少し離れています。

JavaScriptObject json;
    public JavaScriptObject executeQuery(String query) {
        String url = "http://api.domain.com?client_id=xxxx&query=";
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
                URL.encode(url + query));
        try {
            @SuppressWarnings("unused")
            Request request = builder.sendRequest(null, new RequestCallback() {
                public void onError(Request request, Throwable exception) {
                    // violation, etc.)
                }

                public void onResponseReceived(Request request,
                        Response response) {
                    if (200 == response.getStatusCode()) {
                        // Process the response in response.getText()
                        json =parseJson(response.getText());
                    } else {

                    }
                }
            });
        } catch (RequestException e) {
            // Couldn't connect to server
        }
        return json;
    }

    public static native JavaScriptObject parseJson(String jsonStr) /*-{
        return eval(jsonStr );
        ;
    }-*/;

Chromeのデバッガーでは、傘の例外が発生し、スタックトレースを確認できず、GWTデバッガーがNoSuchMethodErrorで終了します...アイデア、ポインターはありますか?

4

5 に答える 5

13

GWT AutoBean Frameworkを見てください。

AutoBean を使用すると、Plain Old Java Object との間で JSON 文字列をシリアライズおよびデシリアライズできます。

私にとって、このフレームワークは不可欠になりました:

  • コードは JSNI オブジェクト (JavaScript Native Interface) よりもクリーンです
  • Google がサポートしていないフレームワークとの依存関係なし (RestyGWT など)

getter と setter を使用してインターフェイスを定義するだけです。

// Declare any bean-like interface with matching getters and setters, 
// no base type is necessary
interface Person {
  Address getAddress();
  String getName();
  void setName(String name):
  void setAddress(Address a);
}

interface Address {
  String getZipcode();
  void setZipcode(String zipCode);
}

後で、ファクトリを使用して JSON 文字列をシリアル化または逆シリアル化できます (ドキュメントを参照)。

// (...)

String serializeToJson(Person person) {
  // Retrieve the AutoBean controller
  AutoBean<Person> bean = AutoBeanUtils.getAutoBean(person);

  return AutoBeanCodex.encode(bean).getPayload();
}

Person deserializeFromJson(String json) {
  AutoBean<Person> bean = AutoBeanCodex.decode(myFactory, Person.class, json);
  return bean.as();
}

// (...)

スタック オーバーフローに関する最初の投稿 (!) : このヘルプが役立つことを願っています :)

于 2011-04-02T17:03:44.073 に答える
5

一般に、説明しているワークフローは次の 4 つのステップで構成されています。

  1. リクエストを行う
  2. JSON テキストを受け取る
  3. JavaScript オブジェクトの JSON を解析する
  4. オーバーレイ タイプを使用してこれらの JavaScript オブジェクトを記述します

すでに手順 1 と 2 が適切に機能しているようです。

JSON を解析する

JSONParser.parseStrictうまくやります。オブジェクトが返されJSONValueます。

これにより、カスタム ネイティブ メソッドの使用を避けることができ、JSON の解析中に任意のコードが実行されるのを防ぐこともできます。JSON ペイロードが信頼されていて、生の速度が必要な場合は、JSONParser.parseLenient. いずれの場合も、独自のパーサー メソッドを記述する必要はありません。

次の JSON を期待しているとしましょう。

{
  "name": "Bob Jones",
  "occupations": [
    "Igloo renovations contractor",
    "Cesium clock cleaner"
  ]
}

JSON がオブジェクトを記述していることがわかっているのでJSONValueJavaScriptObject.

String jsonText = makeRequestAndGetJsonText(); // assume you've already made request
JSONValue jsonValue = JSONParser.parseStrict(jsonText);
JSONObject jsonObject = jsonValue.isObject(); // assert that this is an object
if (jsonObject == null) {
  // uh oh, it wasn't an object after
  // do error handling here
  throw new RuntimeException("JSON payload did not describe an object");
}

オーバーレイタイプとして記述

JSON がオブジェクトを記述していることがわかったので、そのオブジェクトを取得して、JavaScript クラスの観点から記述することができます。このオーバーレイ タイプがあるとします。

class Person {
  String getName() /*-{
    return this.name;
  }-*/;
  JsArray getOccupations() /*-{
    return this.occupations;
  }-*/;
}

キャストを行うことで、新しい JavaScript オブジェクトをこの Java クラスに準拠させることができます。

Person person = jsonObject.getJavaScriptObject().cast();
String name = person.getName(); // name is "Bob Jones"
于 2011-04-01T22:18:06.797 に答える
5
  1. JsonUtils#safeEval()直接呼び出す代わりに、JSON 文字列を評価するために使用しeval()ます。
  2. さらに重要なことは、非同期呼び出しの結果を渡そうとしないことです (コールバックを使用RequestBuilder#sendRequest()して呼び出し元に戻すなど) return

    public void executeQuery(String query,
                             final AsyncCallback<JavaScriptObject> callback)
    {
      ...
      try {
        builder.sendRequest(null, new RequestCallback() {
          public void onError(Request request, Throwable caught) {
            callback.onFailure(caught);
          }
    
          public void onResponseReceived(Request request, Response response) {
            if (Response.SC_OK == response.getStatusCode()) {
              try {
                callback.onSuccess(JsonUtils.safeEval(response.getText()));
              } catch (IllegalArgumentException iax) {
                callback.onFailure(iax);
              }
            } else {
              // Better to use a typed exception here to indicate the specific
              // cause of the failure.
              callback.onFailure(new Exception("Bad return code."));
            }
          }
        });
      } catch (RequestException e) {
        callback.onFailure(e);
      }
    }
    
于 2011-04-01T21:54:30.757 に答える
0

実際には JSON を解析する必要はありません。ネイティブ JSNI オブジェクト (JavaScript Native Interface) を使用できます。

これは、基本的にあなたがやっているのと同じことをしている最近のプロジェクトから私が引っ張ってきた例です:

public class Person extends JavaScriptObject{
    // Overlay types always have protected, zero argument constructors.
    protected Person(){}

    // JSNI methods to get stock data
    public final native String getName() /*-{ return this.name; }-*/;
    public final native String getOccupation() /*-{ return this.occupation; }-*/;

    // Non-JSNI methods below
}

そして、次のように取得します。

/**
   * Convert the string of JSON into JavaScript object.
   * 
   */
  private final native JsArray<Person> asArrayOfPollData(String json) /*-{
    return eval(json);
  }-*/;

private void retrievePeopleList(){

      errorMsgLabel.setVisible(false);

      String url = JSON_URL;
      url = URL.encode(url);

      RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);

      try{
          @SuppressWarnings("unused")
          Request request = builder.sendRequest(null, new RequestCallback() {
            @Override
            public void onResponseReceived(Request req, Response resp) {
                if(resp.getStatusCode() == 200){
                    JsArray<Person> jsonPeople = asArrayOfPeopleData(resp.getText()); 
                    populatePeopleTable(people);
                }
                else{
                    displayError("Couldn't retrieve JSON (" + resp.getStatusText() + ")");
                }
            }

            @Override
            public void onError(Request req, Throwable arg1) {
                System.out.println("couldn't retrieve JSON");
                displayError("Couldn't retrieve JSON");
            }
        });
      } catch(RequestException e) {
          System.out.println("couldn't retrieve JSON");
          displayError("Couldn't retrieve JSON");
      }
  }

したがって、基本的には、応答を JSON オブジェクトの配列としてキャストしています。いい物。

詳細はこちら: http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html

于 2011-04-01T22:43:55.300 に答える
0

サーバーが無効な JSON を返した場合、使用evalは一般的に危険であり、あらゆる種類の奇妙な動作を引き起こす可能性があります (単純に ! を使用する場合、JSON の最上位要素が配列であることが必要であることに注意してくださいeval(jsonStr))。だから私はサーバーが次のような非常に単純な結果を返すようにします

[ "hello" ]

エラーが引き続き発生するかどうか、またはより良いスタック トレースを取得できるかどうかを確認します。

注: GWT ホスト ページと同じ URL + ポート + プロトコルでサーバーに到達できると仮定します (そうしないと、Same Origin Policy により RequestBuilder が動作しません)。

于 2011-04-01T21:32:56.947 に答える