-1

How to use JsonNames to parse multiple names for JSON field in Kotlinx Serialization. For normal data class it works fine

@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class Project(@JsonNames("title") val name: String)

fun main() {
  val project = Json.decodeFromString<Project>("""{"name":"kotlinx.serialization"}""")
  println(project)
  val oldProject = Json.decodeFromString<Project>("""{"title":"kotlinx.coroutines"}""")
  println(oldProject)
}

Project(name=kotlinx.serialization)
Project(name=kotlinx.coroutines)

But for Type generic data class like GoogleBaseApiResponse where T is of any data class

@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class GoogleBaseApiResponse<T> (
    var status : String = "",
    var error_message : String? = null,
    @JsonNames("results", "predictions", "result") var responseData : T? = null
)

Where T is Something like data class or arraylist of data class

Following Errors occurs

Exception in thread "main" java.lang.IllegalStateException: Problem with constructing exception message
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializerClassLowering.lower(SerializationLoweringExtension.kt:184)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:46)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:111)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.declarations.IrClass.acceptChildren(IrClass.kt:68)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptChildrenVoid(IrVisitors.kt:15)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:47)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:111)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.declarations.IrFile.acceptChildren(IrFile.kt:36)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptChildrenVoid(IrVisitors.kt:15)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitElement(SerializationLoweringExtension.kt:42)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitPackageFragment(IrElementVisitorVoid.kt:190)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitPackageFragment(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:200)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:198)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrFile.accept(IrFile.kt:30)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptVoid(IrVisitors.kt:11)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt.runOnFileInOrder(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtension.generate(SerializationLoweringExtension.kt:149)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$lambda$1(JvmIrCodegenFactory.kt:186)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:104)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:218)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:55)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.convertToIr(KotlinToJVMBytecodeCompiler.kt:225)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:102)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:167)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:101)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:79)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:43)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:179)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit$default(CLITool.kt:177)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMain(CLITool.kt:166)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler$Companion.main(K2JVMCompiler.kt:250)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.main(K2JVMCompiler.kt)

Whether is possible to use @JsonNames annotations in Type generic data class?.

Sample Code is below

val httpResponse = httpClient.post {
                    url(PLACES_DETAILS)
                    formData {
                        parameter(PLACE_ID_KEY, userAppLocation.userCityId)
                        parameter(API_KEY, appSettings.getAppConfigModel()?.getMapApiKey())
                    }
                }.call.response
                httpResponse.body<GoogleBaseApiResponse<AddressFromLatLngModel>>().also { apiResponse ->
                    if (apiResponse.status.lowercase() == Constants.OKAY_STATUS.lowercase()) {
                        Napier.d(tag = tag, message = apiResponse.printJSONValue())
                        val newUserAppLocation = userAppLocation.copy(
                            userLat = apiResponse. responseData?.geometry?.location?.lat?:0.0,
                            userLng = apiResponse. responseData?.geometry?.location?.lng?:0.0
                        )
                        emit(NetworkResult.Success(newUserAppLocation))
                    } else {
                        emit(NetworkResult.Error(apiResponse.error_message))
                    }
                }



Where,
GoogleBaseApiResponse --> 
@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class GoogleBaseApiResponse<T> (
    var status : String = "",
    var error_message : String? = null,
    @JsonNames("results", "predictions", "result") var responseData : T? = null
)


AddressFromLatLngModel -->
@Serializable
data class AddressFromLatLngModel(
    var formatted_address : String = "",
    var geometry : GeometryModel = GeometryModel(),
    var address_components : ArrayList<AddressComponentsModel> = arrayListOf()
)

GeometryModel is --> 
@Serializable
data class GeometryModel(
    var location : LocationModel = LocationModel()
)

LocationModel is -->
@Serializable
data class LocationModel(
    var lat : Double = 0.0,
    var lng : Double = 0.0
)

AddressComponentsModel -->
@Serializable
data class AddressComponentsModel(
    var long_name : String = "",
    var short_name : String = ""
)


2 Answers2

0

The code you posted works just fine for me:

    val json = Json.encodeToString(GoogleBaseApiResponse("st", "err", 42))
        .replace("responseData", "predictions") // simulate "alternate" name
    println(json) // {"status":"st","error_message":"err","predictions":42}
    val x = Json.decodeFromString<GoogleBaseApiResponse<Int>>(json)
    println(x) // GoogleBaseApiResponse(status=st, error_message=err, responseData=42)

But since your error happens in the SerializationLoweringExtension, I'd look into configuration regarding that extension, and code that makes use of it. If you post more relevant details, we might be able to help you further.

Jorn
  • 20,612
  • 18
  • 79
  • 126
-1

if i got it you need to user same parameter to different json keys you need to use alternate attribute

so your data class will be like

@Serializable

data class Project(@SerializedName("title",alternate =["name"]) val name: String)

Noah Mohamed
  • 114
  • 1
  • 1
  • 8