9

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?

3
  • what do you mean by "response from my server which is dynamic in nature"? You should know how your server behaves in order to serialize data in your app. Post some server responses Commented Nov 27, 2019 at 9:57
  • @Nicola - I get a JSONArray containing Strings or Integers or a custom object, based on certain conditions. May not be the best schema I agree, but this is something I'm trying to address. Commented Nov 27, 2019 at 10:21
  • I would identify a finite number of response types and for each response I would define a moshi custom adapter Commented Nov 27, 2019 at 10:42

1 Answer 1

11

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.

Sign up to request clarification or add additional context in comments.

1 Comment

for those needing a more detailed example or are working with parsing complex objects see this and this

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.