1

I'm trying to convert a nested Map to a JSONObject like so:

    fun convertToJson(input: Map<String, Any>): JSONObject {
        val jsonObject = JSONObject()
        input.forEach { (key, value) ->
            if (value is Map<*, *>) {
                val iterator = value.entries.iterator()
                while (iterator.hasNext()) {
                    val pairs = iterator.next()
                    (pairs.key as? String)?.let { k ->
                        pairs.value?.let { v ->
                            jsonObject.put(k, v)
                        }
                    }
                }
            }
            jsonObject.put(key, value)
        }
        return jsonObject
    }

(I tried following this example Putting HashMap<String, object> in jsonobject)

I call it like so

val input = mapOf(
  "key1" to mapOf("inner_key1" to "foo"))
val output = convertToJson(input)

What I don't understand, is why is

output.optJSONObject("key1") null? From what I understand, output.opt("key1") returns a Map<*, *>.

That's about as far as I got. I'm not sure if my convertToJson needs fixing, or if my understanding needs correcting, in that, optJSONObject should not be used for nested types and I should use opt if I know the type will be a Map.

2 Answers 2

1

The logic in your code doesn't put keys of a Map into a nested object, but directly into jsonObject. And then it also calls jsonObject.put(key, value) even for a Map (which I am a bit surprised doesn't throw an exception, because it isn't one of the allowed types:

Object: a JSONObject, JSONArray, String, Boolean, Integer, Long, Double, NULL, or null. May not be Double#isNaN() or Double#isInfinite().

).

Assuming keys of any nested Map are strings, I would just do it recursively:

@Suppress("UNCHECKED_CAST")
fun convertToJson(input: Map<String, Any>): JSONObject {
    val jsonObject = JSONObject()
    input.forEach { (key, value) ->
        value1 = if (value is Map<*, *>)
            convertToJson(value as Map<String, Any>)
        else
            value
        jsonObject.put(key, value1)
    }
    return jsonObject
}

(this really should be extended to handle Lists, null, etc. in addition, but that's not part of the question)

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

1 Comment

Derp, thanks. Haven't done Java/Kotlin before until now.
1

Try to put JSONObject inside JSONObject instead of Map<*, *>

fun convertToJson(input: Map<String, Any>): JSONObject {
    val jsonObject = JSONObject()
    input.forEach { (key, value) ->
        if (value is Map<*, *>) {
            val iterator = value.entries.iterator()
            val childObject = JSONObject()
            while (iterator.hasNext()) {
                val pairs = iterator.next()
                (pairs.key as? String)?.let { k ->
                    pairs.value?.let { v ->
                        childObject.put(k, v)
                    }
                }
            }

            jsonObject.put(key, childObject)
        } else {
            jsonObject.put(key, value)
        }
    }
    return jsonObject
}

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.