Retrofit/Moshi request gives error - java.lang.IllegalStateException : dangling name - android

I'm using Retrofit to make some API calls.
Recently, I added a new endpoint
#POST("api/test/myRequest")
fun createRequest(
#retrofit2.http.Body request: MyRequest
): Single<MyResponse>
Using the following DataClass to represent the non-serialized request
data class MyRequest(
#Json(name = "myData") #field:Json(name = "myData") var myData: String,
#Json(name = "myuuid") #field:Json(name = "myuuid") var myuuid: UUID? = null
)
When I try to make the request, it fails with the error: java.lang.IllegalStateException: Dangling name: myuuid
The top item in the stacktrace is: com.squareup.moshi.JsonUtf8Writer. It seems Moshi is throwing an error when trying to serialize the request. It's not clear to me why though.
What does this error mean, and how can I fix it?

I would suggest you to use only one of the annotations, for instance you get the issue if you do not use #Json( name, but only #field
I am not sure and could cancel this post if did not help you, but please try, I am quite curious

Related

Android moshi generic type with different types

I am using retrofit with moshi converter in my android (kotlin) app.
The api response have a general format, where I wrote a class with generic field as the following:
`
#JsonClass(generateAdapter = true)
data class ApiResponse<T>(
#Json(name = "Status")
val status: Boolean,
#Json(name = "Message")
val message: String?,
#Json(name = "Data")
val data: T?
)
`
data field can be of any type. It is working fine in a normal cases. But sometimes the data field in api response comes with different types for the same api.
For example: in login api I have two cases:
Successful login:
{"Status":true, "Message":"Successful Login", "Data":{"userID":"user id", "userName":"user name"}}
Failed login:
{"Status":false, "Message":"Login Failed", "Data":false}
In first case, data is an object, while in second case data is a boolean. So my converter throws an error
I tried to write a custom adapter, to set the data field to null in case it was a boolean in the json, but I failed to handle such generic case, I had to write a custom adapter for every response type.
Is there are anyway to handle this issue without modifying the api code?
Thanks in advance.

Generics in Kotlin Serialization produces compile time error

I am having trouble compiling a Serialization data class that is also a generic. I am very new to Android and Kotlin, but am an experienced iOS/Swift developer (don't hold it against me).
I am trying to set up a generic data class wrapper around a GraphQL Response that can return me either the T generic in a data field, or an error in the error field.
import kotlinx.serialization.Serializable
#Serializable
data class GraphQLResponse<T:Serializable> (
val errors : List<ErrorResponse>? = null,
val data : Map<String, T>? = null
) {
#Serializable
data class Location(
val line: Int? = 0,
val column: Int? = 0,
val sourceName: String? = null
)
#Serializable
data class ErrorResponse(
val locations: List<Location>? = null,
val errorType: String? = null,
val message: String? = null
)
}
Compiling this I get the following error:
java.lang.AssertionError: Couldn't load KotlinClass from /Users/brett/Development/Company/android/app/build/tmp/kotlin-classes/debug/com/company/company/network/GraphQLResponse.class; it may happen because class doesn't have valid Kotlin annotations
And also a bunch of warning around reflection.
Is what I am trying to do possible with Generics and Serialization? Do I need to write my own deserialisation methods ?
Any help and advice would be appreciated.
You need to provide a custom serializer for type T.
check this guide
(BTW, in your code type T shouldn't be Serializable - T:Serializable. It's just annotation)
There is a similar question, check this out.
However, as you can see it may not work well if you use kapt in your project even you provide the serializer.
I found this comment from the serialization repository :
However, due to the mentioned kapt issue, it's impossible for now. Probably, a viable workaround can be to move models and serializers to the separate Gradle module, which is not processed by kapt.
And there are more issues about this problem :
https://github.com/Kotlin/kotlinx.serialization/issues/1148
https://github.com/Kotlin/kotlinx.serialization/issues/685
https://github.com/Kotlin/kotlinx.serialization/issues/1313

Gson Pojo class

I'm making cryptocurrency information viewer now. I use Retrofit to get response, but have some problem.
https://api.coinone.co.kr/ticker/?currency=all
This is the api I use. and its structure is... too complicated to make pojo class.
if I make convert this to pojo class, then pojo class will be like
data class Coinone(
val result: String,
val errorCode: String,
val timestamp: String,
val crypto1: Ticker,
val crypto2: Ticker,
val crypto3: Ticker,
...
val cryptoN: Ticker)
Should I do like that? Is that only one solution?
I mean, if api data would be updated, I must update my pojo class. If I don't, apps will surely make crushes.
Is there any solution for making pojo class with api having similar structure?
Gson Object used when I don't know about Retrofit, GsonConverter and Kotlin not so much.

How can I parse JSON such that if the structure is not as I intended it gracefully fails?

Reference: https://bytes.babbel.com/en/articles/2018-05-25-kotlin-gson-nullability.html
This article talks about one of the shortcomings of GSON with Kotlin. If we have a data class like this and try to break it:
data class User(
val email: String,
val firstName: String)
fun main(args: Array<String>) {
val json = """{
"email": null
}"""
val gson = Gson()
println(gson.fromJson(json, User::class.java).email)
}
as soon as we parse it and use the email field we'll return a NullPointerException. This is the intended behavior of GSON.
Is there a library out there that can give me an error like IllegalStateException and validate which field should be nullable? Or, is there a way to work around Moshi or GSON or any other JSON library so that I can get errors like that?
Gson doesn't give NullPointerException if a field is missing.It just ignores the missing fields of the object. For more details i would request you to share error log with exception and the code.

only classes are allowed on the left hand side of a class literal

I know a lot of similar questions here in StackOverflow, but nothing solved mine.
I have a generic data class:
data class ServiceCall<out T>(val result: T?, val exception: String?, val pagination: String?, val stringResult: String?)
I am trying to use like this:
Gson().fromJson(json, ServiceCall<SurveyListModel>::class.java).result
IDE shows error: only classes are allowed on the left hand side of a class literal
How to solve this? Thanks in advance.
You can't use generics with class, as easily observable here:
List<Int>::class.java
It gives you the same error. To use the generic typ in GSON deserialization, do what is suggested here:
https://stackoverflow.com/a/5554296/8073652
EDIT:
In Kotlin it looks like this:
val type: Type = object : TypeToken<ServiceCall<SurveyListModel>>() {}.type
Gson().fromJson<ServiceCall<SurveyListModel>>(json, type).result
Here's a small proof of concept, I've written:
class Token : TypeToken<List<Int>>()
val x: List<Int> = Gson().fromJson(Gson().toJson(arrayOf(1)), Token().type)
println(x)
If someone looking for the answer in Kotlin and Jackson.
val response = ObjectMapper().convertValue(dataObject, object: TypeReference<Map<String, Any>>(){})
If you want to pass a list of the generic objects pass it like this
listOf<MyModel>()::class
the function will be like this
fun myFunction ( inputList: KClass<T>){}

Categories

Resources