2

In my Android app (written in Kotlin), I need to turn some JSON into a string to MainObject hash map. This is what the JSON looks like:

{
    "a": {
        "name": "A",
        "some_int": "2",
        "some_string": "string",
        "some_bool": false,
        "some_string_arr": [
            "str1",
            "str2"
        ],
        "sub_obj_arr": [
            {
                "obj_name": "d",
                "some_obj_string": "s"
            }
        ]
    },
    "b": {
        "name": "B",
        "some_int": "4",
        "some_string": "string",
        "some_bool": false,
        "some_string_arr": [
            "str5",
            "str6"
        ]
    }
}

I created a couple of objects to help with this.

class MainObject {
    @SerializedName("name")
    val name: String? = null

    @SerializedName("some_int")
    val someInt: Int? = null

    @SerializedName("some_string")
    val someString: String? = null

    @SerializedName("some_bool")
    val someBool: Boolean = false

    @SerializedName("some_string_arr")
    val someStringArr: List<String>? = null

    @SerializedName("sub_obj_arr")
    val someObjArr: List<SubObject>? = null
}

class SubObject {
    @SerializedName("obj_name")
    val objName: String? = null

    @SerializedName("some_obj_string")
    val someObjString: String? = null
}

How do I convert this into a type of HashMap<String, MainObject>? I tried using a TypeToken as described here, but I was getting the error "expected begin object but was string".

Any ideas?

UPDATE

I'm also reading in the JSON data locally via the solution described here

Error Log

10-15 20:06:42.771 10328-10328/xxx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: xxx, PID: 10328
    java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
     Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
        at com.google.gson.Gson.fromJson(Gson.java:900)
        at com.google.gson.Gson.fromJson(Gson.java:853)
        at com.google.gson.Gson.fromJson(Gson.java:802)
        at xxx.onCreate(BottomNavigation.kt:48)
        at android.app.Activity.performCreate(Activity.java:6975)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6541) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 
     Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
        at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
        at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:183)
        at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
        at com.google.gson.Gson.fromJson(Gson.java:888)
        at com.google.gson.Gson.fromJson(Gson.java:853) 
        at com.google.gson.Gson.fromJson(Gson.java:802) 
        at xxx.onCreate(BottomNavigation.kt:48) 
        at android.app.Activity.performCreate(Activity.java:6975) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6541) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 

Update 2

The actual issue is something wrong with the way I am reading in my local JSON file. The code I use is this:

val input = this.resources.openRawResource(R.raw.json)
val json = try {
    val size = input.available()
    val buffer = ByteArray(size)
    input.read(buffer)
    input.close()
    String(buffer)
} catch (ex: IOException) {
    ex.printStackTrace()
    null
}

Which gives me these weird characters when I print out the json to the console:

10-15 23:55:11.911 3351-3351/xxx I/System.out: ��{����

10-15 23:55:11.911 3351-3351/xxx I/System.out: �� �� �� �� ��"��a��"��:�� ��{����

No idea why though.

2
  • Please share the whole error log. Commented Oct 16, 2017 at 1:31
  • Updated it with the error log Commented Oct 16, 2017 at 2:49

2 Answers 2

10

I don't know why you have any error. I am able to parse the JSON with following code.

val gson = GsonBuilder().create()
val type = object:TypeToken<Map<String, MainObject>>(){}.type
val result = gson.fromJson<Map<String, MainObject>>("{ \"a\": { \"name\": \"A\", \"some_int\": \"2\", \"some_string\": \"string\", \"some_bool\": false, \"some_string_arr\": [ \"str1\", \"str2\" ], \"sub_obj_arr\": [ { \"obj_name\": \"d\", \"some_obj_string\": \"s\" } ] }, \"b\": { \"name\": \"B\", \"some_int\": \"4\", \"some_string\": \"string\", \"some_bool\": false, \"some_string_arr\": [ \"str5\", \"str6\" ] } }", type)
Sign up to request clarification or add additional context in comments.

2 Comments

Hmm, interesting. Thanks for running that test for me. That makes me think there is something wrong with the way I'm reading in the JSON file itself.
This doesn't seem to work for me, when I use object:TypeToken<Map<LocalDate, Int>>(){}.type . It causes IllegalStateException: Expected BEGIN_OBJECT but was STRING at line ... . Any idea why? Asked here: stackoverflow.com/q/77741719/878126
0

Okay, with the help of others I figured out that the issue wasn't with Gson or my JSON or anything. It was in the way I was reading it into memory. The code I was using was:

val input = this.resources.openRawResource(R.raw.json)
val json = try {
    val size = input.available()
    val buffer = ByteArray(size)
    input.read(buffer)
    input.close()
    String(buffer)
} catch (ex: IOException) {
    ex.printStackTrace()
    null
}

However, String(buffer) defaults to using UTF_8 charset. In order for mine to work, I needed to use a UTF_16 charset. The working change was using String(buffer, Charsets.UTF_16).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.