Why Gson #Expose annotation not working properly? - android

I have a model class that fills with server response by gson.
the gson converter factory is:
Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())
I have a transient field inside my model to prevent serialize/deserialize by gson.
data class Testy(
val id:Int = 1,
#Transient var isShowing:Boolean = true
):Serializable
after getting server response and get the converted gson object, the value of isShowing field is false while I expected to be true(as init value).
Workaround
I have used below ways but I didn't get the desired behavior:
using #Expose(serialize = false, deserialize = false) instead of #Transient
as mentiond here adding GsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT)

Related

Is it possible to use kotlinx-datetime with Gson

I have JSON data which is retrieved from the local realm database. I'm trying to convert it into the corresponding data class. I have an ISO date field
{
....
"createdAt" : "2022-05-04T10:16:56.489Z"
....
}
What I'm trying to do is to convert this string date field into kotlinx-datetime's Instant object which is a serializable class. Thus I made my data class as
import kotlinx.datetime.Instant
data class PollPinComment(
...
val createdAt: Instant? = null,
...
)
Which doesn't work and gives an error as follows
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 288 path $[0].createdAt
I'm sure that I might need to write some serialization/deserialization logic with gson to convert this string into Instant object. So my question is how can I do that? Thanks in advance
GSON parses only basic data types, such as Int, String, double...
Other classes that need to be parsed must also consist of these basic data types.
could do like this:
data class PollPinComment(val createdAt: String ){
fun getCreatedAt(): Instant{
return Instant.parse(createdAt)
}
}
You can create a custom Deserializer for this and register it as type adapter to your Gson object.
class InstantDateDeserializer: JsonDeserializer<Instant> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): Instant? {
return json?.asString?.let {
Instant.parse(it)
}
}
}
Create Gson() object pasing that deserializer as type adapter
val gson: Gson = GsonBuilder ()
.registerTypeAdapter(Instant::class.java, DateDeserializer())
.create()
If you are using it with Retrofit
In Retrofit builder pass this to GsonConverterFactory
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()

Parsing a jsonrray into object using moshi with Retrofit and Kotlin

I am trying to parse using Moshi Library for JSON Array using Kotlin Coroutines .
Code use
fun retrofitIndia(baseUrl : String) : Retrofit = Retrofit.Builder()
.client(clientIndia)
.baseUrl(baseUrl)
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
I get issue while Parsing the data class for JSON Array . I have used same for JSON Object and it works fine but during array , it crashes
Below is the crash line
java.lang.IllegalArgumentException: Unable to create converter for java.util.ArrayList<data.india.Delta2>
I call from Globallaunch coroutine where it gets failed
Code :
GlobalScope.launch(Dispatchers.Main) {
val statsRequest = i.getStats()
try {
val response = statsRequest.await()
if(response.){
val statsResponse = response.body() //This is single object Tmdb Movie response
Log.i("stats",""+statsResponse)
}else{
Log.d("MainActivity ",response.errorBody().toString())
}
}catch (e: Exception){
Log.e("Exception",e.localizedMessage)
}
}
You should make the type just List<T>, Moshi only supports the collection interfaces, not the concrete collection classes like ArrayList<T>, LinkedList<T>, etc.. The same goes for other kinds of collections: use Set<T> instead of HashSet<T>, and Map<K, V> instead of HashMap<K, V>, etc..
I don't think the coroutines have anything with the parsing error, try following Reading Json lists using Moshi
Quick snippet will look something like:
// Single item declaration
class SingleListItem(val title: String, val number: Int)
private var listMyData = Types.newParameterizedType(MutableList::class.java, SingleListItem::class.java)
private val adapter: JsonAdapter<List<SingleListItem>> = Moshi.Builder().add(KotlinJsonAdapterFactory()).build().adapter(listMyData)

Configure Moshi for Room TypeConverter

Given that I'm already using Moshi to convert the Retrofit response from JSON String to Objects, can I also configure the Room Database on Android to use Moshi for TypeConverter instead of manually typing up the TypeConverter functions and referencing Moshi?
Example of some code that I have been writing that I think seems redundant.
#TypeConverter
fun fromJsonToPictures(value: String): List<PictureObject>? {
val moshi = Moshi.Builder().build()
val type = Types.newParameterizedType(List::class.java, PictureObject::class.java)
val adapter = moshi.adapter<List<PictureObject>>(type)
return adapter.fromJson(value)
}

Retrofit2 and Gson, deserialize data inside a certain json element

Inside my app i call some remote APIs that give me a response wrapped into a useless "root" json element. I Paste you an example of json response
{
"response": {
"status": {
//here status fields, common to all responses
},
"configuration": {
//here configurations fields
}
}
}
I'm using an Android studio extension for generate kotlin data classes (JsonToKotlinClass) and i obtain four kotlin classes:
-MyResponseClass, Response, Status, Configuration
where MyResponseClass is like
data class MyResponseClass(
val response: Response
)
there's a way to avoid creation of "Response" class by parsing only it's relative json content and get a MyResponseClass look like like
data class MyResponseClass(
val status:Status,
val configuration: Configuration
)
?
From the title of your question I am assuming that you want to automatically parse the json response to the to the simpler MyResponseClass
You can achieve this by using a type adapter for gson. In your case the adapter class will look similar to the following.
class MyResponseClassAdapter : JsonDeserializer<MyResponseClass> {
override fun deserialize(jsonElement: JsonElement, p1: Type?, p2: JsonDeserializationContext?): MyResponseClass {
val content = jsonElement.asJsonObject["response"]
return Gson().fromJson(content , MyResponseClass::class.java)
}
}
Then add this adapter to a gson instance and use that gson instance with your retrofit instance.
val gson = GsonBuilder()
.registerTypeAdapter(MyResponseClass::class.java, MyResponseClassAdapter ())
.create()
Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl("{base_url}")
.client(okHttp)
.build()
Yes, when you get the object, instead of converting it straight away, convert it like this
val jsonObject = JSONObject("data")
val innerObject = jsonObject.getJSONObject("status")
and then convert inner object with gson.
This can of course be minified like this:
val object = Gson().fromJson(JSONObject("response").getJSONObject("status"), MyResponseClass::class.java)

Android retrofit missing fields in the POJO

I am using Retrofit to get the data from the API and parse it into a POJO object.
However, the API is not documented and I am not very sure what data does the JSON contain.
I have field in my POJO for the data I am sure is coming, but at times they are fields in the JSON that I have not accounted for.
Obviously, Retrofit just ignores these fields.
How can I make it send a warning when a field in the JSON is NOT in the POJO?
class User {
#SerializedName("id")
private Integer id;
#SerializedName("name")
private String name;
[relevant getters and setters]
}
The JSON that is coming is:
{
id: 5,
name: "John",
age: 23
}
Age field is not in the POJO, but at application does not throw any error; how do I make it display an error in such instances?
You may consider using Jackson to deserialize your POJO.
Then you can use the following annotations:
#JsonIgnoreProperties(ignoreUnknown = false)

Categories

Resources