I have a simple Json class that handles retrofit perfectly.
But there is no timestamp in it.
I add my custom field which is not in json, but it is always null
//Custom field for timestamp
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
//My class for JSON respons
#Entity(tableName = "nal")
data class CurrencyItem(
#PrimaryKey(autoGenerate = true)
val id:Long,
#SerializedName("base_ccy")
var baseCcy: String,
#SerializedName("buy")
val buy: String,
#SerializedName("ccy")
val ccy: String,
#SerializedName("sale")
val sale: String,
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
)
Simplest solution add custom field in model for timestamp.
val timeStamp: String
Аnd when retrofit response come, rewrite this null field with timestamp, i use method SimpleDateFormat
// retrofit response
var res = resp.body()
// new list which i create and rewrite with timestamp and then return
var l = ArrayList<CurrencyItem>()
//read response list with json converted data
for (r in res.orEmpty()){
l.add(CurrencyItem(1 ,
r.baseCcy,
r.buy,
r.ccy,
r.sale,
SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())))
}
//return this new list with timestamp. I use repository pattern with livedata
response.value = l
Related
I am using retrofit (Im new to it) and gson to serialize an object into a json to send through an api (POST). The object has a date field, and when serializing it, it is not recognized by the api, which responds with:
{"detail":[{"loc":["body","birth_date"],"msg":"invalid date format","type":"value_error.date"}]}
My class:
data class User(
var name: String = "",
var email: String = "",
#PrimaryKey(autoGenerate = false)
var id: String = UUID.randomUUID().toString(),
var sex: String? = null,
#SerializedName("birth_date")
var birthDate: Date = Date()
)
My call to the API:
#POST("user/me")
suspend fun createUser(#Header(AUTH_HEADER) token: String, #Body user: User): Response<User>
By the API documentation, the date format should be:
"birth_date": "2022-12-22"
How can i change the value of birthDate to match the api format on the request body?
As you can see
"birth_date": "2022-12-22"
above date value is in String format.
try by changing the data type Date to String
data class User(
....
#SerializedName("birth_date")
var birthDate: String = ""
)
Hope it will work :)
I have this type of array in firebase but how to fetch it and use in kotlin
I was able to get as String but how to get its as a data class Like this
data class Comment(
val uid: String,
val comment: String,
val stamp: Timestamp
)
and here's the code of getting string
var text by remember { mutableStateOf("loading...") }
FirebaseFirestore.getInstance().collection("MyApp")
.document("Something").get().addOnSuccessListener {
text = it.get("Comments").toString()
}
Firebase has a toObject method that can be used to turn your document into a custom object.
db.collection("Comments")
.get()
.addOnSuccessListener { documents ->
for (document in documents) {
val comment = document.toObject<Comment>()
}
}
The Comment data class should also define default values. So, it should be like...
data class Comment(
val uid: String = "",
val comment: String = "",
#ServerTimeStamp val stamp: Date? = null
)
I got ArrayLists with HashMaps represents my entities entities just using this:
val cleanAnswers: List<Answer> = (document.get(FIELD_ANSWERS)
as ArrayList<HashMap<String, Any>>).map {
Answer(
it[FIELD_VARIANT] as String,
it[FIELD_IS_CORRECT] as Boolean
)
}
My entity:
class Answer(val answer: String,
val isCorrect: Boolean) : Serializable
The Class that I'm using with toJson
class LoadUserDTO: Serializable {
#SerializedName("userGuid")
var userGuid: String? = null
#SerializedName("userToken")
var userToken: String? = null
constructor(userGuid: String, userToken: String) {
this.userGuid = userGuid
this.userToken = userToken
}
}
And the rest of the use:
val payload = LoadUserDTO(userGuid = user.guid!!, userToken = user.token!!)
val jsonPayload = Gson().toJson(payload)
this.socketService.socket.emit(EndpointsEnum.AppLoadUser, jsonPayload)
The jsonPayload should be a JSON Object. Instead, the entire thing is a String of what should be a JSON Object:
"{"userGuid":"...","userToken":"..."}"
When this is received by the server, it's not receiving a JSON Object as the Web UI or Swift App sends, but is instead just a String, not converted to a JSON Object.
try this,
var jsonString = """{"id":1,"description":"Test"}""";
var testModel = gson.fromJson(jsonString, TestModel::class.java)
Based on your requirement instead using Gson you may use String.format to achieve this by one line of code -
// val payload = LoadUserDTO(userGuid = user.guid!!, userToken = user.token!!)
// val jsonPayload = Gson().toJson(payload)
val jsonPayload = String.format("\"{\"userGuid\": \"%s\"," + "\"userToken\": \"%s\"" + "}\"",user.guid,user.token)
// Log.d("ZI",jsonPayload)
Output- example
"{"userGuid": "1234","userToken": "token000"}"
You may remove space after : while formatting string .
val jsonPayload = String.format("\"{\"userGuid\":\"%s\"," + "\"userToken\":\"%s\"" + "}\"",user.guid,user.token)
Output-
"{"userGuid":"1234","userToken":"token000"}"
I don't fully understand why yet, but this SO Question gave me the answer for it to work:
Send JSON data from in socket.io from android
val jsonPayload = Gson().toJson(payload)
val jsonObj = JSONObject(jsonPayload)
this.socketService.socket.emit(EndpointsEnum.AppLoadUser, jsonObj)
After making the jsonObj the server now has a properly formed JSON Object that it can work with.
I am working on an android application that uses Firebase Firestore as a database. I am trying to store a list of SoldItems where each soldItem has a PrescriptionType formed from Sealed classes.
data class SoldItem(var itemName : String = "",
var quantity : String = "",
var totalPrice : Int = 0,
var itemQuantityType: ItemQuantityType = ItemQuantityType.SINGLE,
var prescriptionType: String = ""
) : Serializable
prescriptionType while defined as a string is originally a Sealed Class PrescriptionType
sealed class PrescriptionType : Parcelable {
// Check how to parcelize objects
#Parcelize
data class Syrup(var quantityInMls : Double = 2.5, var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay) : PrescriptionType()
#Parcelize
data class Lotion(var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay): PrescriptionType()
#Parcelize
data class Capsule(var quantity : Int = 1, var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay ) : PrescriptionType()}
I store prescriptionType as a string because of the lack of support in FirebaseFirestore android SDK directly for sealed classes. I've had to create my own TypeConverter. This works quite well in generating a string (JSON) from each prescriptionType and also generating a prescriptionType from the string.
#JvmStatic
#TypeConverter
fun fromPrescription(prescriptionType: PrescriptionType) : String{
val prescriptionAdapterFactory : RuntimeTypeAdapterFactory<PrescriptionType> = RuntimeTypeAdapterFactory.
of(PrescriptionType::class.java, "type")
.registerSubtype(PrescriptionType.Syrup::class.java, "Syrup")
.registerSubtype(PrescriptionType.Lotion::class.java, "Lotion")
.registerSubtype(PrescriptionType.Capsule::class.java, "Capsule")
val gsonBuilder = GsonBuilder().registerTypeAdapterFactory(prescriptionAdapterFactory).create()
return "\"" +gsonBuilder.toJson(prescriptionType, PrescriptionType::class.java) + "\""
}
#JvmStatic
#TypeConverter
fun toPrescriptionType(prescriptionType : String) : PrescriptionType {
val prescriptionAdapterFactory : RuntimeTypeAdapterFactory<PrescriptionType> = RuntimeTypeAdapterFactory.
of(PrescriptionType::class.java, "type")
.registerSubtype(PrescriptionType.Syrup::class.java, "Syrup")
.registerSubtype(PrescriptionType.Lotion::class.java, "Lotion")
.registerSubtype(PrescriptionType.Capsule::class.java, "Capsule")
val gsonBuilder = GsonBuilder().registerTypeAdapterFactory(prescriptionAdapterFactory).create()
return gsonBuilder.fromJson(prescriptionType, PrescriptionType::class.java)
}
}
Storing the string works quite well in the database. The object is stored and everything is fine - we can see that the prescriptionType is a string.
However in retrieving soldItems in Firebase, we encounter an issue where it seems the firebase SDK returns the JSON string and converts it to an object and hence crashes as prescriptionType is a String not an object.
val soldItemsType = object : TypeToken<List<SoldItem>>() {}.type
val soldItemsFromBackend = it.get("soldItems").toString()
Timber.d(soldItemsFromBackend)
val soldItems = Gson().fromJson<List<SoldItem>>(
soldItemsFromBackend,
soldItemsType
)
Logging soldItemsFromBackend gives
[{drugQuantityType=SINGLE, prescriptionType={"type":"Capsule","frequency":"Stat","quantity":1,"time":"OneDay"}, itemName=Docusate, quantity=2, totalPrice=0}]
and trying to create soldItems using Gson gives an error
Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 46 path $[0].prescriptionType
I think Gson wants to parse prescriptionType as a string but instead sees an object. I've tried to pad the prescriptionType string with extra quotes but it still didn't work.
Does anyone please know how I can retrieve prescriptionType as a string?
I have one issue about code data class kotlin android.
How to implement server response? sometimes I get String value or sometime get Object class.
class CMSRespTemp {
data class CMSRespApi(
val status: Boolean = false,
val message: String = "",
val data: String as Data
)
data class Data(
val cms_id: String = "",
val cms_content: String = ""
)
}
When I implement only Data class it works, like this val data: Data or val data: String. But I need together Data and String with key only data.
Is it possible?
When having multiple type for same variable, we can use Any type which is equivalent to Object type in java. So solution is like below :
class CMSRespTemp {
data class CMSRespApi(
val status: Boolean = false,
val message: String = "",
var data: Any? = null // changed it to var from val, so that we can change it's type runtime if required
)
data class Data(
val cms_id: String = "",
val cms_content: String = ""
)
}
And when accessing that variable, one can simply cast like below :
val apiResponse : CMSRespApi //= some API response here from network call
when (apiResponse.data) {
is String -> {
// apiResponse.data will be smart-casted to String here
}
else -> {
val responseData = Gson().fromJson<CMSRespApi.Data>(
Gson().toJsonTree(apiResponse.data),
CMSRespApi.Data::class.java
)
}
}
After 12 Hrs spend and got the solution my self,
val getResultCon = getSerCont.result // response Any
val gson = Gson()
val jsonElement = gson.toJsonTree(getResultCon)
val resultData = gson.fromJson(jsonElement, SearchContactApi.Result::class.java)
Convert your data string to toJsonTree and fromJson with model class then got result.