Search code examples
jsonplayn

In the HTML version of PlayN, why does the following JSON-handling code throw an exception?


I'm trying to figure out if this is a bug within HtmlJson.java or in my implementation. I just upgraded to PlayN version 1.2. My code attempts to load a Json.Object into a Json.Writer. This works in the Java version.

This is the code below. The exception is raised by line jsonWriter.object(jsonData); (note comment in code):

private void loadStoredData() {
    // storage parameters
    String storageKey = "jsonData";
    Json.Object jsonData = PlayN.json().createObject();        

    // attempt to load stored data
    String jsonString = PlayN.storage().getItem(storageKey);

    // if not loaded, create stored data
    if ( jsonString == null ) {
        DemoApi.log("stored data not found");
        jsonData.put("firstWrite", new Date().toString());

    // else display data
    } else {
        jsonData = PlayN.json().parse(jsonString);
        DemoApi.log("stored data loaded");
        DemoApi.log("data first written at " + jsonData.getString("firstWrite"));
        DemoApi.log("data last read at " + jsonData.getString("lastRead"));
        DemoApi.log("data last written at " + jsonData.getString("lastWrite"));
    }

    // update last read
    jsonData.put("lastRead", new Date().toString());

    // write data
    Json.Writer jsonWriter = PlayN.json().newWriter();
    jsonWriter.object(jsonData);        // <--- EXCEPTION RAISED HERE
    jsonString = jsonWriter.write();

    // store data as json
    PlayN.storage().setItem(storageKey, jsonString);

    // confirm
    if ( PlayN.storage().isPersisted() ) {
        DemoApi.log("data successfully persisted");
    } else {
        DemoApi.log("failed to persist data");
    }
}

The exception:

ERROR: Uncaught Exception: 
java.lang.ClassCastException: com.google.gwt.core.client.JavaScriptObject$ cannot be cast to java.lang.String
    at playn.html.HtmlJson$HtmlObject$.write$(HtmlJson.java:356)
    at com.google.gwt.core.client.JavaScriptObject$.playn_core_Json$Object_write(JavaScriptObject.java)
    at playn.core.json.JsonWriterBase.object(JsonWriterBase.java:119)
    at playn.core.json.JsonWriterBase.object(JsonWriterBase.java:90)
    at klenwell.sandbox.core.controllers.SandboxController.loadStoredData(SandboxController.java:121)

If this is a bug in my code, how might I correct it?


Solution

  • I found an alternative. Not quite as elegant as the original code, but it tested successfully in HTML5:

    private void loadStoredData() {
        // storage parameters
        String storageKey = "jsonData";
        Json.Object jsonData = PlayN.json().createObject();  
    
        // to reset storage, uncomment this line
        //PlayN.storage().removeItem(storageKey);
    
        // attempt to load stored data
        String jsonString = PlayN.storage().getItem(storageKey);
    
        // if not loaded, create stored data
        if ( jsonString == null ) {
            DemoApi.log("stored data not found");
            jsonData.put("firstWrite", new Date().toString());
    
        // else display data
        } else {
            jsonData = PlayN.json().parse(jsonString);
            DemoApi.log("stored data loaded");
            DemoApi.log("data first written at " + jsonData.getString("firstWrite"));
            DemoApi.log("data last read at " + jsonData.getString("lastRead"));
            DemoApi.log("data last written at " + jsonData.getString("lastWrite"));
        }
    
        // update last read
        jsonData.put("lastRead", new Date().toString());
    
        // write data (this works in Java -- not in HTML)
        // see http://stackoverflow.com/q/10425877/1093087
        /*
        Json.Writer jsonWriter = PlayN.json().newWriter();
        jsonWriter.object(jsonData).end();
        jsonString = jsonWriter.write();
        */
    
        // alternative write routine
        Json.Writer jsonWriter = PlayN.json().newWriter();
        jsonWriter.object();
        for ( String key : jsonData.keys() ) {
            jsonWriter.value(key, jsonData.getString(key));
        }
        jsonWriter.end();
        jsonString = jsonWriter.write();
    
        // store data as json
        PlayN.storage().setItem(storageKey, jsonString);
    
        // confirm
        if ( PlayN.storage().isPersisted() ) {
            DemoApi.log("data successfully persisted");
        } else {
            DemoApi.log("failed to persist data");
        }
    }
    

    DemoApi.log, for the record, is a method I hatched to log output to the screen when testing in the browser. I later discovered that the PlayN.log() service logs to the Chrome console fine.