Loading JSON from String into JSONArray on Android

I've been experiencing some problems for quite some time trying to load a JSON string into a JSONArray. I was hoping a post here would help me solve the problem.

The file is located in the assets folder and contain objects of the class Kabelskap. The JSON string is formatted like this excerpt:

[{"driftsmerking":"1420 10 04","objektnummer":"56569.0","adresse":"KANEBOGÅSEN    4","fabrikat":"NEBB","typebetegnelse":"KO500","spenning":"0.23","posisjon":"OK","kompNr":"1420","kommune":"1901 HARSTAD","latitude":"68.7786964342854","longitude":"16.5598512563035"},{"driftsmerking":"4416 01 04","objektnummer":"246349.0","adresse":"NONSÅSEN","fabrikat":"ABB","typebetegnelse":"KO300","spenning":"0.23","posisjon":"OK","kompNr":"4416","kommune":"1911 KVÆFJORD","latitude":"68.7367985627796","longitude":"16.2694481350258"},{"driftsmerking":"4080 05 02","objektnummer":"275933.0","adresse":"KVÆFJORD PLANTESKOLE VEKSTHUS","fabrikat":"ABB","typebetegnelse":"KO700","spenning":"0.23","posisjon":"OK","kompNr":"4080","kommune":"1911 KVÆFJORD","latitude":"68.7712454761326","longitude":"16.1901046355049"},{"driftsmerking":"1383 01 02","objektnummer":"150951.0","adresse":"SKILLEVN. 13","fabrikat":"ABB","typebetegnelse":"","spenning":"0.4","posisjon":"OK","kompNr":"1383","kommune":"1901 HARSTAD","latitude":"68.7781436806564","longitude":"16.5643438120601"},{"driftsmerking":"4085 07 02","objektnummer":"275122.0","adresse":"MATHUSET","fabrikat":"NEBB","typebetegnelse":"70","spenning":"0.23","posisjon":"OK","kompNr":"4085","kommune":"1911 KVÆFJORD","latitude":"68.7721426826508","longitude":"16.1785193494225"}]

This string is read into a String variable which is then passed on into this code segment:

try {
    JSONObject jsonObj = new JSONObject(finalString);

    for(int i = 0; i < json.length(); i++){
        Kabelskap ks = (Kabelskap) json.get(i);
        skap.put(ks.objektnummer, ks);
    }
} catch (JSONException e) {
    e.printStackTrace();
}

This should, according to what I expected, return an JSON array which I then could iterate through and cast into objects of my class.

11-30 00:31:33.568: INFO/System.out(389): {"driftsmerking":"1420 10 04","objektnummer":"56569.0","adresse":"KANEBOG�SEN 4","fabrikat":"NEBB","typebetegnelse":"KO500","spenning":"0.23","posisjon":"OK","kompNr":"1420","kommune":"1901 HARSTAD","latitude":"68.7786964342854","longitude":"16.5598512563035"}{"driftsmerking":"4416 01 04","objektnummer":"246349.0","adresse":"NONS�SEN","fabrikat":"ABB","typebetegnelse":"KO300","spenning":"0.23","posisjon":"OK","kompNr":"4416","kommune":"1911 KV�FJORD","latitude":"68.7367985627796","longitude":"16.2694481350258"}{"driftsmerking":"4080 05 02","objektnummer":"275933.0","adresse":"KV�FJORD PLANTESKOLE VEKSTHUS","fabrikat":"ABB","typebetegnelse":"KO700","spenning":"0.23","posisjon":"OK","kompNr":"4080","kommune":"1911 KV�FJORD","latitude":"68.7712454761326","longitude":"16.1901046355049"}{"driftsmerking":"1383 01 02","objektnummer":"150951.0","adresse":"SKILLEVN. 13" of type org.json.JSONObject cannot be converted to JSONArray
11-30 00:31:33.588: WARN/System.err(389):     at org.json.JSON.typeMismatch(JSON.java:107)
11-30 00:31:33.588: WARN/System.err(389):     at org.json.JSONArray.<init>(JSONArray.java:91)
11-30 00:31:33.588: WARN/System.err(389):     at org.json.JSONArray.<init>(JSONArray.java:103)
11-30 00:31:33.588: WARN/System.err(389):     at net.lovholm.kraftwerk.Kraftwerk.onCreate(Kraftwerk.java:68)

This error message indicates that there should be a problem with the formatting, but to check this I have tested the JSON structure against some online validators and it seems to be valid.

The String as it is returned from the log seems to use a different encoding than that of the file UTF-8. I'm not sure whether this may be a part of the problem or if this is just the character encoding of the log console.

Any suggestion to this problem is very welcome.

---- UPDATE ---- ---- UPDATE ---- ---- UPDATE ---- ---- UPDATE ----

I have now updated the code with the suggestions from aj.esler, which corrects some of the mistakes I did in the code excerpt above. Here is a longer excerpt from my code, and I still experience problem with the error message above. It seems this line JSONArray json = new JSONArray(finalString); causes something malicious to happen in the JSONArray constructor. The String passed in should accomodate the requirements of the API with valid JSON syntax and opening square brackets.

try {
    AssetManager assetManager = getAssets();
    fis = assetManager.open(sourcePath);
    BufferedReader bw = new BufferedReader(new InputStreamReader(fis, "utf8"));
    while ((str = bw.readLine()) != null){
        finalString += str;
    }
} catch (FileNotFoundException e) {
        e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

System.out.println(finalString);

try {
    JSONArray json = new JSONArray(finalString);

    for(int i = 0; i < json.length(); i++){
        JSONObject jsonObj = json.getJSONObject(i);
        try {
        Kabelskap ks = getKabelskapFromJSON(jsonObj);
        skap.put(ks.objektnummer, ks);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
} catch (JSONException e) {
    e.printStackTrace();
}

----- UPDATE 2.0 --------

The System.out.println(finalString) > Not sure whether the reader or the System.out.println() skips long parts of the text. I would presume that the DDMS LogCat is using a charset not supporting Norwegian special letters.

11-30 11:02:27.888: INFO/System.out(4304): {"driftsmerking":"1420 10 04","objektnummer":"56569.0","adresse":"KANEBOG�SEN 4","fabrikat":"NEBB","typebetegnelse":"KO500","spenning":"0.23","posisjon":"OK","kompNr":"1420","kommune":"1901 HARSTAD","latitude":"68.7786964342854","longitude":"16.5598512563035"}{"driftsmerking":"4416 01 04","objektnummer":"246349.0","adresse":"NONS�SEN","fabrikat":"ABB","typebetegnelse":"KO300","spenning":"0.23","posisjon":"OK","kompNr":"4416","kommune":"1911 KV�FJORD","latitude":"68.7367985627796","longitude":"16.2694481350258"}{"driftsmerking":"4080 05 02","objektnummer":"275933.0","adresse":"KV�FJORD PLANTESKOLE VEKSTHUS","fabrikat":"ABB","typebetegnelse":"KO700","spenning":"0.23","posisjon":"OK","kompNr":"4080","kommune":"1911 KV�FJORD","latitude":"68.7712454761326","longitude":"16.1901046355049"}{"driftsmerking":"1383 01 02","objektnummer":"150951.0","adresse":"SKILLEVN. 13","fabrikat":"ABB","typebetegnelse":"","spenning":"0.4","posisjon":"OK","kompNr":"1383","kommune":"1901 HARSTAD","latitude":"68.7781436806564","longitude":"16.5643438120601"}{"driftsmerking":"4085 07 02","objektnummer":"275122.0","adresse":"MATHUSET","fabrikat":"NEBB","typebetegnelse":"70","spenning":"0.23","posisjon":"OK","kompNr":"4085","kommune":"1911 KV�FJORD","latitude":"68.7721426826508","longitude":"16.1785193494225"}{"driftsmerking":"3410 05 12","objektnummer":"35184.0","adresse":"HANS EGEDESGT. 20 (ERIKSGATE)","fabrikat":"NEBB","typebetegnelse":"","spenning":"0.23","posisjon":"OK","kompNr":"3410","kommune":"1901 HARSTAD","latitude":"68.7980203542316","longitude":"16.538182961594"}{"driftsmerking":"0800 06 10","objektnummer":"266928.0","adresse":"GAMNES V/MAGNE HARALD OLSEN","fabrikat":"ABB","typebetegnelse":"KO35","spenning":"0.23","posisjon":"OK","kompNr":"","kommune":"1901 HARSTAD","latitude":"68.8206299498345","longitude":"16.4915959572276"}{"driftsmerking":"2580 02 02","objektnummer":"186379.0","adresse":"RESSAN","fabrikat":"ELMEK","typebetegnelse":"50 CM","spenning":"0.23","posisjon":"OK","kompNr":"2580","kommune":"1913 SK�NLAND","latitude":"68.6729130202412","longitude":"17.127746958547"}{"driftsmerking":"1500 10 06","objektnummer":"193875.0","adresse":"TUVSLETTVN. 9","fabrikat":"ABB","typebetegnelse":"KO500","spenning":"0.23","posisjon":"OK","kompNr":"1500","kommune":"1901 HARSTAD","latitude":"68.74741783798","longitude":"16.5517037722856"}{"driftsmerking":"3282 02 02","objektnummer":"35547.0","adresse":"TEGEB�RVN. 12B","fabrikat":"NEBB","typebetegnelse":"","spenning":"0.23","posisjon":"OK","kompNr":"3282","kommune":"1901 HARSTAD","latitude":"68.7991934883357","longitude":"16.5033927383319"}{"driftsmerking":"1430 05 02","objektnummer":"116375.0","adresse":"�VERLAND 2","fabrikat":"ABB","typebetegnelse":"KO700","spenning":"0.23","posisjon":"OK","kompNr":"1430","kommune":"1901 HARSTAD","latitude":"68.7759663213591","longitude":"16.5611455110691"}{"driftsmerking":"4150 05 06","objektnummer":"275496.0","adresse":" NYVN. 21","fabrikat":"ABB","typebetegnelse":"KO500","spenning":"0.4","posisjon":"OK","kompNr":"4150","kommune":"1911 KV�FJORD","latitude":"68.7741925557284","longitude":"16.1726621696438"}{"driftsmerking":"1486 07 02","objektnummer":"162192.0","adresse":"ROHOLTVN. 7","fabrikat":"ABB","typebetegnelse":"KO 700","spenning":"0.23","posisjon":"OK","kompNr":"1486","kommune":"1901 HARSTAD","latitude":"68.7550368601091","longitude":"16.5679658964195"}{"driftsmerking":"3025 02 06 / 3060 /","objektnummer":"35174.0","adresse":"HANS EGEDESGT. 6 (HVEDINGSGATE)","fabrikat":"NEBB","typebetegnelse":"","spenning":"0.23","posisjon":"OK","kompNr":"3025","kommune":"1901 HARSTAD","latitude":"68.7994885383443","longitude":"16.5414817371666"}{"driftsmerking":"7045 03 06","objektnummer":"251410.0","adresse":"KONGSVIKDALEN","fabrikat":"","typebetegnelse":"","spenning":"0.23","posisjon":"OK","kompNr":"7045","kommune":"1852 TJELDSUND","latitude":"68.5682671357777","longitude":"16.2428412985428"}{"driftsmerking":"3010 03 02","objektnummer":"35143.0","adresse":"6.DIVISJONSGT. 10","fabrikat":"ABB","typebetegnelse":"KO500",

-- New update --

The full error trace from the JSONArray(String json) constructor:

12-03 15:14:44.290: WARN/System.err(412): org.json.JSONException: Value {"posisjon":"OK","spenning":"0.23","driftsmerking":"1420 10 04","adresse":"KANEBOG�SEN 4","kompNr":"1420","objektnummer":"56569.0","typebetegnelse":"KO500","longitude":"16.5598512563035","latitude":"68.7786964342854","kommune":"1901 HARSTAD","fabrikat":"NEBB"} of type org.json.JSONObject cannot be converted to JSONArray
12-03 15:14:44.290: WARN/System.err(412):     at org.json.JSON.typeMismatch(JSON.java:107) 
12-03 15:14:44.290: WARN/System.err(412):     at org.json.JSONArray.<init>(JSONArray.java:91)
12-03 15:14:44.290: WARN/System.err(412):     at org.json.JSONArray.<init>(JSONArray.java:103)
12-03 15:14:44.290: WARN/System.err(412):     at net.lovholm.kraftwerk.Kraftwerk.onCreate(Kraftwerk.java:66)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
12-03 15:14:44.290: WARN/System.err(412):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-03 15:14:44.290: WARN/System.err(412):     at android.os.Looper.loop(Looper.java:130)
12-03 15:14:44.290: WARN/System.err(412):     at android.app.ActivityThread.main(ActivityThread.java:3683)
12-03 15:14:44.290: WARN/System.err(412):     at java.lang.reflect.Method.invokeNative(Native Method)
12-03 15:14:44.290: WARN/System.err(412):     at java.lang.reflect.Method.invoke(Method.java:507)
12-03 15:14:44.290: WARN/System.err(412):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
12-03 15:14:44.290: WARN/System.err(412):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
12-03 15:14:44.290: WARN/System.err(412):     at dalvik.system.NativeStart.main(Native Method)

The implementation of the JSONArray initialisation and the getKabelskapfromJSON method:

  1. JSON Array initialisation excerpt

    try { JSONArray json = new JSONArray(finalString);

    for(int i = 0; i < json.length(); i++){
        JSONObject jsonObj = json.getJSONObject(i);
        try {
        Kabelskap ks = getKabelskapFromJSON(jsonObj);
        skap.put(ks.objektnummer, ks);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    

    } catch (JSONException e) { e.printStackTrace(); }

  2. getKabelselskapFromJSON method:

    private Kabelskap getKabelskapFromJSON(JSONObject jsonObj) throws JSONException {

    String driftsmerking = jsonObj.getString("driftsmerking");
    
    String adresse = jsonObj.getString("addresse");
    
    String objektnummer = jsonObj.getString("objektnummer");
    
    String spenning = jsonObj.getString("spenning");
    
    String fabrikat = jsonObj.getString("fabrikat");
    
    String typebetegnelse = jsonObj.getString("typebetegnelse");
    
    String posisjon = jsonObj.getString("posisjon");
    
    String kompNr = jsonObj.getString("kompNr");
    
    String kommune = jsonObj.getString("kommune");
    
    String latitude = jsonObj.getString("latitude");
    
    String longitude = jsonObj.getString("longitude");
    
    Kabelskap k = new Kabelskap(driftsmerking, objektnummer, adresse, fabrikat, typebetegnelse, spenning, posisjon, kompNr, kommune, latitude, longitude);
    
    return k;
    

}

Answers


A few problems I can see:

  1. You use jsonObj on the first line, which is a JSONObject. Then in the for loop, you use a different object called json. I'm going to assume that these two are the same object. Otherwise, there is information missing from your example.
  2. JSONObject does not have a method get that takes an integer. There is one that takes a string, so I will assume you meant that one.
  3. JSONObject.get returns the data corresponding to the key you give it. It returns an Object.

The error you are getting is because you are trying to cast an JSONObject to a Kabelskap.

What I would do is create a helper method like below. Alternatively, you could create a special constructor on the Kabelstap object.

public Kabelskap getKabelskapFromJSON(JSONObject jsonObj)
{
    Kabelskap k = new Kabelskap();

    String driftsmerking = jsonObj.getString("driftsmerking");
    k.setDriftsmerking(driftsmerking);

    String addresse = jsonObj.getString("addresse");
    k.setAddresse(addresse);

    String objektnummer = jsonObj.getString("objektnummer");
    k.setObjektNummer(objektnummer);

    double spenning = jsonObj.getDouble("spenning");
    k.setSpenning(spenning);

    // ... and so on for each property.

    return k;
}

which can then be used like so:

try {
    JSONArray jsonArray = new JSONArray(yourJSONString);
    for(int i = 0; i < jsonArray.length(); i++)
    {
        JSONObject jsonObj = jsonArray.getJSONObject(i);
        Kabelskap k = getKabelskapFromJSON(jsonObj);
        // do something with k. eg
        System.out.println("Kabelskap@"+i+": "+k);
    }
} catch (JSONException e) {
    e.printStackTrace();
}

Documentation for JSONObject is here and JSONArray is here.


Need Your Help

Are storyboards widely used on iOS apps?

ios objective-c frameworks storyboard xcode-storyboard

I am currently developing a iOS framework for other developers to use. I intend to use "ECSlidingViewController" framework and add it a webView to that Slide-Up. I already have it working on two pr...

How to make java use millimeters instead of pixels?

java printing size lwjgl image-resizing

My problem is that what I size a picture according to millimeters to pixels, and then print it out this will never be exact.