Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use Moshi to serialize a json string into org.json.JSONObject?

Tags:

json

kotlin

moshi

I have a JSON response from my server which is dynamic in nature and I cannot map it into a Kotlin Data Class.

I would like to create a org.json.JSONObject out of it and parse it from there. I've looked around SO and Moshi's doc but couldn't find any easy way of achieving this.

Any suggestions?

like image 544
Jignesh Shah Avatar asked Nov 27 '19 09:11

Jignesh Shah


People also ask

What is Moshi JSON?

Moshi is a modern JSON library for Android and Java from Square. It can be considered as the successor to GSON, with a simpler and leaner API and an architecture enabling better performance through the use of the Okio library.

What is the use of Moshi?

Moshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin classes: Note: The Kotlin examples of this README assume use of either Kotlin code gen or KotlinJsonAdapterFactory for reflection.

Can we convert JSONArray to JSONObject?

We can also add a JSONArray to JSONObject. We need to add a few items to an ArrayList first and pass this list to the put() method of JSONArray class and finally add this array to JSONObject using the put() method.


1 Answers

I've stumbled upon the same problem recently. I needed to resend some of the data from one endpoint to another with adding some new stuff to it.

The response from the server looks like this:

{
    "someProperty": "value",
    "someOtherProperty": "otherValue",
    "someDynamicProperty": {
        // There may be anything including nested structures, not known beforehand
    }
}

Normally Moshi doesn't have built-in support for something like this, but it allows you to build your own adapters and handle the parsing logic.

What you need is define the type that you want to receive as a result:

@JsonClass(generateAdapter = true)
data class CustomResponse(
    val someProperty: String,
    val someOtherProperty: String,
    val someDynamicProperty: JSONObject?
)

Then, you need to create a custom adapter to handle the parsing:

internal object JSONObjectAdapter {

    @FromJson
    fun fromJson(reader: JsonReader): JSONObject? {
        // Here we're expecting the JSON object, it is processed as Map<String, Any> by Moshi
        return (reader.readJsonValue() as? Map<String, Any>)?.let { data ->
            try {
                JSONObject(data)
            } catch (e: JSONException) {
                // Handle error if arises
            }
        }
    }

    @ToJson
    fun toJson(writer: JsonWriter, value: JSONObject?) {
        value?.let { writer.value(Buffer().writeUtf8(value.toString())) }
    }
}

Then, just add this adapter to Moshi builder on creation:

Moshi.Builder().add(JSONObjectAdapter).build()

or use Moshi annotations if you want to apply it only to some particular properties.

like image 143
Georgiy Shur Avatar answered Nov 15 '22 08:11

Georgiy Shur