Search code examples
javagwtjsniautobean

AutoBean, Arrays/Lists properties and JSNI


I am somehow struggling with Arrays and JSNI in the context of Autobeans.
In one of my GWT projects I retrieve a data from backend using JSON.
Once the data is retrieved on the client I want to visualize it using a custom visualization widgets (developed in javascript).

Here are the components:

JSON structure:

{'ids':[1,2,3,4],'data':[[1.0],[1.0,2.0],[1.0,2.0,3.0] ... ]}

Basically I have two datasets in my json payload. ids is a array of ints (int[]) and data is a array of arrays of floats (float[][])

There are of course different ways to parse the data on the client. I decided to use AutoBeans. So I defined an interface for my json structure.

AutoBean:

interface MyData {
   List<Integer> ids;
   List<List<Float>> data;
}

Parsing the data works fine.

My custom visualization widgets has a API function to set the data that looks like this:

function api_setData(ids,data) {
   //ids should be an Array of Ints
   //data should be an array of array of Floats.
}

The problem is that with JSNI I can't use normal Java arrays. I have to use JsArray.

public final native void setData(JsArrayInteger ids,JsArray<JsArrayInteger> data /*-{
       this.api_setData(ids,data);
    }-*/;

So I have to convert my AutoBean properties (data and ids) to JsArray instances. Is there a better/nicer way to do that?

Or maybe I should use JSONParser instead of AutoBeans Is that more efficient?


Solution

  • If you have to deal with JSNI, moreover if you're using your MyData interface only on the client-side, then don't use AutoBeans. Use JSON overlays instead:

    public class MyData extends JavaScriptObject {
       protected MyData() { /* required for JSOs */ }
    
       public final native JsArrayInteger getIds() /*-{ return this.ids; }-*/;
    
       public final native JsArray<JsArrayNumber> getData() /*-{ return this.data; }-*/;
    }
    

    And then to parse your JSON:

    MyData data = JsonUtils.safeEval(jsonStr);
    customVisualizationWidget.setData(data.getIds(), data.getData());
    

    Alternately, assuming you only need you parsed data for setData, then simply use JavaScriptObject.

    In your widget:

    public final native void setData(JavaScriptObject obj) /*-{
       this.api_setData(obj.ids, obj.data);
    }-*/;
    

    When you need to parse the JSON and give it to the widget:

    customVisualizationWidget.setData(JsonUtils.safeParse(jsonStr));