All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.kotlinx.serialization.SerializersJvm.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */
@file:JvmMultifileClass
@file:JvmName("SerializersKt")
package kotlinx.serialization

import kotlinx.serialization.builtins.*
import kotlinx.serialization.internal.*
import java.lang.reflect.*
import kotlin.reflect.*

/**
 * Constructs a serializer for the given reflective Java [type].
 * [serializer] is intended to be used as an interoperability layer for libraries like GSON and Retrofit,
 * that operate with reflective Java [Type] and cannot use [typeOf].
 *
 * For application-level serialization, it is recommended to use `serializer()` instead as it is aware of
 * Kotlin-specific type information, such as nullability, sealed classes and object.
 */
@Suppress("UNCHECKED_CAST")
@OptIn(UnsafeSerializationApi::class)
public fun serializer(type: Type): KSerializer = when (type) {
    // TODO stabilize for Spring
    is GenericArrayType -> {
        val eType = type.genericComponentType.let {
            when (it) {
                is WildcardType -> it.upperBounds.first()
                else -> it
            }
        }
        val serializer = serializer(eType)
        val kclass = when (eType) {
            is ParameterizedType -> (eType.rawType as Class<*>).kotlin
            is KClass<*> -> eType
            else -> throw IllegalStateException("unsupported type in GenericArray: ${eType::class}")
        } as KClass
        ArraySerializer(kclass, serializer) as KSerializer
    }
    is Class<*> -> if (!type.isArray) {
        (type.kotlin as KClass).serializer()
    } else {
        val eType: Class<*> = type.componentType
        val s = serializer(eType)
        val arraySerializer = ArraySerializer(eType.kotlin as KClass, s)
        arraySerializer as KSerializer
    }
    is ParameterizedType -> {
        val rootClass = (type.rawType as Class<*>)
        val args = (type.actualTypeArguments)
        when {
            List::class.java.isAssignableFrom(rootClass) -> ListSerializer(serializer(args[0])) as KSerializer
            Set::class.java.isAssignableFrom(rootClass) -> SetSerializer(serializer(args[0])) as KSerializer
            Map::class.java.isAssignableFrom(rootClass) -> MapSerializer(
                serializer(args[0]),
                serializer(args[1])
            ) as KSerializer
            Map.Entry::class.java.isAssignableFrom(rootClass) -> MapEntrySerializer(
                serializer(args[0]),
                serializer(args[1])
            ) as KSerializer

            else -> {
                // probably we should deprecate this method because it can't differ nullable vs non-nullable types
                // since it uses Java TypeToken, not Kotlin one
                val varargs = args.map { serializer(it) as KSerializer }.toTypedArray()
                (rootClass.kotlin.constructSerializerForGivenTypeArgs(*varargs) as? KSerializer)
                        ?: (rootClass.kotlin as KClass).serializer()
            }
        }
    }
    is WildcardType -> serializer(type.upperBounds.first())
    else -> throw IllegalArgumentException("typeToken should be an instance of Class, GenericArray, ParametrizedType or WildcardType, but actual type is $type ${type::class}")
}

@Deprecated("Deprecated during serialization 1.0 API stabilization", ReplaceWith("serializer(type)"), level = DeprecationLevel.ERROR)
public fun serializerByTypeToken(type: Type): KSerializer = serializer(type)

@Deprecated("Deprecated during serialization 1.0 API stabilization", ReplaceWith("typeOf()"), level = DeprecationLevel.ERROR)
public inline fun  typeTokenOf(): Type = error("Should not be called")




© 2015 - 2025 Weber Informatics LLC | Privacy Policy