Home > other >  Kotlin: Cannot convert Map to JSON
Kotlin: Cannot convert Map to JSON

Time:07-31

How to convert Map to JSONObject? It accepts Map but it seems you need to perform casting. Is there any other way to do this without using library?

enter image description here

CodePudding user response:

I just realized the answer, if you are using Map like Map<String, String> in Kotlin there is a mutable and immutable version of it. In the question above all you need to do is to convert it to immutable Map using toMap().

val msgData = parser.fromJsonString<CommonNotification>(
            JSONObject(remoteMessage.data.toMap()).toString(),
            CommonNotification::class.java
        ) ?: return

CodePudding user response:

The answer provided by Bitwise DEVS may work, but the explanation is incorrect.

It is not necessary to convert the map into an immutable map - it can even be seen in the screenshot of the question: expected (Mutable)Map means that it can be mutable or immutable.

The real problem here is that the called constructor of JSONObject is defined for Map<Any?, Any?> but the given parameter is of type Map<String!, String!>. We know that String is a subtype of Any?, so why is that a problem?

It is a problem because Map is invariant in the key parameter which means that a Map<A, V> is not subtype of Map<B, V> even if A is subtype of B (and also not if it is the other way around).

The call of toMap does not work because it makes the map immutable, but because it is defined as

fun <K, V> Map<out K, V>.toMap(): Map<K, V>

In the receiver type of toMap the key parameter is annotated with the out modifier, meaning that K is covariant here. This means that a Map<Any, V> in this position can safely be considered as a supertype of Map<String, V>. Additionally, Map is always covariant in its value type, meaning that Map<Any, Any> in this position can safely be considered as a supertype of Map<String, String>.

You could as well just cast remoteMessage.data as Map<Any?, Any?> or use toMutableMap, it would be all the same. It has definitely nothing to do with mutability of the map.

Kotlin documentation on variance: https://kotlinlang.org/docs/generics.html#declaration-site-variance

Kotlin documentation of Map: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/

Definition of toMap: https://github.com/JetBrains/kotlin/blob/ea836fd46a1fef07d77c96f9d7e8d7807f793453/libraries/stdlib/src/kotlin/collections/Maps.kt#L600

  • Related