this is json output:
{"query":{"apikey":"...","base_currency":"USD","timestamp":1635972203},"data":{"JPY":113.99127,"CNY":6.39464,"CHF":0.9114,"CAD":1.23881,"MXN":20.54423,"INR":74.44808,"BRL":5.57063,"RUB":71.80098,"KRW":1175.11443,"IDR":14295.1734,"TRY":9.63691,"SAR":3.75119,"SEK":8.52554,"NGN":410.22181,"PLN":3.94541,"ARS":99.81213,"NOK":8.49529,"TWD":27.78459,"IRR":42000.64577,"AED":3.67284,"COP":3827.77643,"THB":33.32047,"ZAR":15.23269,"DKK":6.40357,"MYR":4.15212,"SGD":1.34783,"ILS":3.11624,"HKD":7.78416,"EGP":15.7003,"PHP":50.65881,"CLP":811.73282,"PKR":169.4547,"IQD":1458.01958,"DZD":136.722,"KZT":428.93534,"QAR":3.6499,"CZK":21.94293,"PEN":4.0008,"RON":4.25921,"VND":22747.41599,"BDT":85.57148,"HUF":308.78687,"UAH":26.25062,"AOA":598.0065,"MAD":9.06226,"OMR":0.38491,"CUC":24.00026,"BYR":2.00003,"AZN":1.69502,"LKR":200.00259,"SDG":438.90856,"SYP":2511.07513,"MMK":1746.02836,"DOP":56.29093,"UZS":10690.31508,"KES":111.25137,"GTQ":7.73108,"URY":44.18107,"HRV":6.47553,"MOP":8.01811,"ETB":47.31305,"CRC":635.74442,"TZS":2298.03956,"TMT":3.49009,"TND":2.80635,"PAB":1.00002,"LBP":1505.5263,"RSD":101.16202,"LYD":4.54568,"GHS":6.00013,"YER":249.956,"BOB":6.82018,"BHD":0.377,"CDF":1999.22628,"PYG":6875.19435,"UGX":3550.05822,"SVC":8.7497,"TTD":6.74137,"AFN":90.84208,"NPR":119.13277,"HNL":24.06657,"BIH":1.68483,"BND":1.34753,"ISK":129.16264,"KHR":4060.117,"GEL":3.14003,"MZN":63.22108,"BWP":11.45513,"PGK":3.5113,"JMD":153.22216,"XAF":564.86281,"NAD":15.2189,"ALL":105.53113,"SSP":391.0052,"MUR":42.90097,"MNT":2830.04693,"NIO":35.21094,"LAK":10330.27262,"MKD":53.08156,"AMD":474.80501,"MGA":3928.06091,"XPF":102.48118,"TJS":11.26034,"HTG":98.0013,"BSD":1.00003,"MDL":17.41883,"RWF":1018.02194,"KGS":84.77099,"GNF":9510.20822,"SRD":21.40242,"SLL":10779.18736,"XOF":568.81159,"MWK":807.36713,"FJD":2.06806,"ERN":15.05028,"SZL":15.21372,"GYD":207.78611,"BIF":1980.25293,"KYD":0.82002,"MVR":15.42042,"LSL":15.23032,"LRD":146.80405,"CVE":94.95278,"DJF":177.50237,"SCR":14.42749,"SOS":575.00647,"GMD":52.15123,"KMF":424.6543,"STD":21.11031,"XRP":0.83002,"AUD":1.34372,"BGN":1.68394,"BTC":0.0159,"JOD":0.70801,"GBP":0.73402,"ETH":0.00022,"EUR":0.86112,"LTC":0,"NZD":1.40184}}
The data section contains many key value pairs, but their number and names vary according to base_currency. (For example if i send request with USD there is no USD key or if i send request with CNY there is no CNY key in data section)
So what kind of data class should I create so that I can use it with the retrofit and gsoncreator libraries. (I am also trying to use and learn jetpack android libraries if this is important)
i use that data classes: (I am not using gson annotations because i believe my variables names are correct and i try that it doesn't help)
data class ResponseFromApi(val data: Data,val query: Query)
data class Query(val apikey: String, val base_currency: String, val timestamp: Int)
data class Data(val hashmapForData: HashMap<String, Double>) (i suspect some values are integer but i am not sure)
it doesn't work. Maybe that's not the problem. I don't know but least i need to know, Are these classes correct? What is the proper way to do this.
And i don't know how to get error message from retrofit object so i can identify the problem. But this is another question.
Arpit Shukla's answer is correct.
ResponseFromApi(val query: Query, val data: Map<String,Double>)
It can deserialize key-value map to Map struct.
I am facing a problem when trying to send an Http post request to the backend of my application. I am trying to send a post request like this :
{"a":[{"data":"https://news.google.com/rss/search?q=Pallini&hl=el"}]}
and instead it is being send something like this:
{"a":[{"data\":\"https://news.google.com/rss/search?q=Pallini&hl=el"}]}
or:
{"a":[{\"data\":\"https://news.google.com/rss/search?q=Pallini&hl=el\"}]}
So, I have a list that contains strings and every time I add the string that I want it to be shown in the json array, the code is like this:
var arrayListForA: ArrayList<JsonElement>? = arrayListOf()
config.forEach {
arrayListForA?.add(it)
}
The config is an another list that contains the jsons object as strings.
My question is, if there is any way to create the http post request body in Kotlin with the use of classes, objects etc, in a more automated way ?! for example, instead of a list with strings, I could use a list with Data class objects.
val dataList : ArrayList<Data> = arrayListOf()
where Data class is :
#Parcelize
data class Data(
#Expose #SerializedName("data") val data: String?
) : Parcelable
Is there any solution/idea to send the body of the post request as I need it ?
You can use retrofit and okhttp for this in Android. Retrofit helps you deal with networking easily. Also you will be able to post a custom data model as body in the api request. The interface will look something like given below. You can read more about retrofit here. retrofit
#POST(Urls.PURCHASE)
fun purchase(#Body purchaseAddonReqModel: PurchaseReqModel):Single<BaseResponse<EmptyResponse>>
Here you can add your custom model by adding the #Body annotation
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.
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>){}