If I have this url address
https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117
How could I get (or split) parameters (avoiding hard coding)?
I need separated values:
https
googledroids.com
/post.html
parameters and values: {limit=25, time=0dfdbac117, since=1374196005, md5=d8959d12ab687ed5db978cb078f1e}
The following should work, it gives a list of parameter values rather than just one.
val uri = Uri.parse("https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117")
val host = uri.host // googledroids.com
val protocol = uri.scheme // https
val path = uri.path // /post.html
val parameters = uri.queryParameterNames.associateWith { uri.getQueryParameters(it) } // {limit:[25], time:[0dfdbac117], since:[1374196005], md5:[d8959d12ab687ed5db978cb078f1e]}
Using the class:
import android.net.Uri
We can the values protocol, server, path, parameters and we have the option to get a specific parameter value using uri.getQueryParameter():
val url = "https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117"
val uri = Uri.parse(url)
val protocol = uri.scheme // https
val server = uri.authority // googledroids.com
val path = uri.path // /post.html
val args = uri.queryParameterNames //size: 4 parameters
val limit = uri.getQueryParameter("limit") // limit: "25"
println("value of limit: $limit")
we can get a list of parameters too (Using this question´s answer (java)):
val url = "https://googledroids.com/post.html?limit=25&since=1374196005&md5=d8959d12ab687ed5db978cb078f1e&time=0dfdbac117"
val uri = Uri.parse(url)
val protocol = uri.scheme // https
val server = uri.authority // googledroids.com
val path = uri.path // /post.html
val args = uri.queryParameterNames //size: 4 parameters
val query = uri.query
val data: MutableMap<String, String> = HashMap()
for (param in query?.split("&")?.toTypedArray()!!) {
val params = param.split("=").toTypedArray()
val paramName = URLDecoder.decode(params[0], UTF_8)
var value = ""
if (params.size == 2) {
value = URLDecoder.decode(params[1], UTF_8)
}
data[paramName] = value
}
println("$data") //{limit=25, time=0dfdbac117, since=1374196005, md5=d8959d12ab687ed5db978cb078f1e}
this is a better and easy way to get the paramaters and values using uri.queryParameterNames:
val uri = Uri.parse(url)
val protocol = uri.scheme
val server = uri.authority
val path = uri.path
val args = uri.queryParameterNames
val limit = uri.getQueryParameter("limit")
val query = uri.query
for (paramName in uri.queryParameterNames) {
println("parameter => $paramName | value: ${uri.getQueryParameter(paramName)}")
}
}
Related
So I have been tackling this issue for a couple of days now. I have a Data class that is used to send information back into the API. In this instance, I have this x amount of fields. In these fields, there are three List fields with different types, as such.
The Data Classes
data class ApiSurveySiteUpdateBody(
#SerializedName("UserId") val userId: Int,
#SerializedName("SStatusId") val sStatusId: Int,
#SerializedName("SSId") val sSId: Int,
#SerializedName("SPONum") val sPoNum: Int,
#SerializedName("WorkPerformanceTypeId") val workPerformTypeId: Int,
#SerializedName("SSAddressId") val sSAddressId: Int,
#SerializedName("WorktoPerformDate") val workToBePerformedDate: String,
#SerializedName("CableRun") val cableRun: String,
#SerializedName("Entrance") val entranceInfo: String,
#SerializedName("DoorLockHardware") val doorLockHardware: String,
#SerializedName("HandicapOperator") val handicapOperator: String,
#SerializedName("DeviceComplete") val completedPrimaryDeviceList: List<Int>,
#SerializedName("TemplateId") val templateId: Int,
#SerializedName("NewDeviceList") val newDeviceList: List<ApiNewDeviceList> = emptyList(),
#SerializedName("UpdateDeviceList") val updateDeviceList: List<ApiUpdateDeviceList> = emptyList(),
#SerializedName("RemoveDeviceList") val removedDeviceList: List<ApiRemovedDeviceList> = emptyList()
)
The Converter function
private fun getSomeRequestBody(
dbInfo: DbFormWithEList,
apiSurveySiteMedias: List<ApiSSMediaInfo>
)
: ApiSSUpdateBody {
val updateRequestApi = ApiSSUpdateBody(
userId = dbInfo.sSDbInfo.userId,
sSId = dbInfo.sSDbInfo.sSId,
sStatusId = dbInfo.sStatusDbInfo.sSId,
sPoNum = dbInfo.sSDbInfo.sPoNumber,
workPerformTypeId = dbInfo.sSDbInfo.workPerformTypeId,
sSAddressId = dbInfo.sSDbInfo.sSAddressId,
workToBePerformedDate = dbInfo.sSDbInfo.workToBePerformedDate,
cableRun = dbInfo.sSDbInfo.cableRun,
entranceInfo = dbInfo.sSDbInfo.entranceInfo,
doorLockHardware = dbInfo.sSDbInfo.doorLockHardware,
handicapOperator = dbInfo.sSDbInfo.handicapOperator,
completedPrimaryDeviceList = dbInfo.sSDbInfo.completedPrimaryDeviceList.toIntList(),
templateId = dbInfo.sSDbInfo.templateId,
newDeviceList = List(dbInfo.equipmentList.size) { i -> // “NewDeviceList”
val dbEquipmentInfo = dbInfo.equipmentList[i].sSEquipmentDbInfo
Log.d(TAG, "NewDeviceListDB $dbEquipmentInfo")
val secondaryDeviceCheckedStatus = dbEquipmentInfo.secondaryDeviceCheckedStatus
val isDuplicateDeviceInUpdatePhase = dbEquipmentInfo.isDeviceUpdateMode
if (sDeviceCheckedS == CHECKED_YES && !isDuplicateDUP){
val newDeviceListRequestBody = ApiNewDeviceList(
secondaryDeviceId = dbEquipmentInfo.secondaryDeviceId,
deviceInstanceId = dbEquipmentInfo.deviceInstanceId.toString(),
mediaNameList = dbEquipmentInfo.mediaNames,
deviceSerialNumber = dbEquipmentInfo.deviceSerialNumber,
devicePartNumber = dbEquipmentInfo.devicePartNumber,
deviceManufacturerName = dbEquipmentInfo.deviceManufacturer,
deviceInstallationDate = DateUtil.dateToStringUTCSS(dbEquipmentInfo.deviceInstallationDate),
deviceLocation = dbEquipmentInfo.locationInfo,
deviceTechnicianNotes = dbEquipmentInfo.deviceTechnicianNotes
)
Log.d(TAG, "newDeviceListRequestBodyAPI $newDeviceListRequestBody")
newDeviceListRequestBody
}
else if (sDeviceCheckedS == CHECKED_NO){
apiDeviceListMapperUpdateSS.sendDeviceNotExistsInNewDeviceList(dbEquipmentInfo)
}
else {
apiDeviceListMapperUpdateSS.sendEmptyNewDeviceList()
}
},
updateDeviceList = (List(dbInfo.equipmentList.size) { i ->
val dbEquipmentInfo = dbInfo.equipmentList[i].sSEquipmentDbInfo
Log.d("UpdatingSiteSurvey", "UpdateDeviceListDB $dbEquipmentInfo")
val secondaryDeviceCheckedStatus = dbEquipmentInfo.secondaryDeviceCheckedStatus
val isDuplicateDeviceInUpdatePhase = dbEquipmentInfo.isDeviceUpdateMode
if (secondaryDeviceCheckedStatus == CHECKED_YES && isDuplicateDeviceInUpdatePhase){
val updateDeviceListRequestBody = ApiUpdateDeviceList(
deviceEquipmentId = dbEquipmentInfo.deviceEquipmentId,
secondaryDeviceId = dbEquipmentInfo.secondaryDeviceId,
deviceInstanceId = dbEquipmentInfo.deviceInstanceId.toString(),
deviceSerialNumber = dbEquipmentInfo.deviceSerialNumber,
devicePartNumber = dbEquipmentInfo.devicePartNumber,
deviceManufacturerName = dbEquipmentInfo.deviceManufacturer,
deviceInstallationDate = DateUtil.dateToStringUTCSiteSurvey(dbEquipmentInfo.deviceInstallationDate),
deviceLocation = dbEquipmentInfo.locationInfo,
deviceTechnicianNotes = dbEquipmentInfo.deviceTechnicianNotes
)
Log.d(TAG, "updateDeviceListRequestBodyAPI $updateDeviceListRequestBody")
updateDeviceListRequestBody
} else Unit.apply { } //<- the issue is here
}) as List<ApiUpdateDeviceList>,
removedDeviceList = List(dbInfo.sSDbInfo.removedDeviceList.size) { i ->
val dbRemovedMediaItem = dbInfo.sSDbInfo.removedDeviceList[i]
Log.d(TAG, "RemovedListDB $dbRemovedMediaItem")
if (dbRemovedMediaItem.removedDeviceEquipmentId == null && dbRemovedMediaItem.removedMediaName.isNullOrEmpty()){
val removeDevice = apiDeviceListMapperUpdateSiteSurvey.removeDevice(dbRemovedMediaItem)
Log.d(TAG, "removeDevice $removeDevice")
removeDevice
}else{
val removeMediaForExistingDevice = apiDeviceListMapperUpdateSS.removeMediaForExistingDevice(dbRemovedMediaItem)
Log.d(TAG, "removeMediaForExistingDevice $removeMediaForExistingDevice")
removeMediaForExistingDevice
}
}
)
Log.d(TAG, "MainUpdateRequestAPI $updateRequestApi")
return updateRequestApi
}
The goal is to have the else statement that is highlighted to return an emptyList "[]" to that updateDeviceList field. I have tried a few ways but never was able to return that exact empty list "[]". Any help will be appreciated. Thank you.
I can't tell if you want (1) the whole list to be invalidated and become empty if any item in the iteration fails the if check, or if you just want (2) to filter out items that fail the if check. But here's how I would approach each of those tasks.
I am breaking out the conversion between DbEquipmentInfo and ApiUpdateDeviceList into a separate extension function (fun DbEquipmentInfo.toApiUpdateDeviceList(): ApiUpdateDeviceList). Not just to avoid code repetition, but also to keep the logic code easy to read, and make the project's code more maintainable in general.
1.
val isValid = dbInfo.equipmentList.all { dbEquipmentInfo ->
val secondaryDeviceCheckedStatus = dbEquipmentInfo.secondaryDeviceCheckedStatus
val isDuplicateDeviceInUpdatePhase = dbEquipmentInfo.isDeviceUpdateMode
secondaryDeviceCheckedStatus == CHECKED_YES && isDuplicateDeviceInUpdatePhase
}
updateDeviceList =
if (isValid) dbInfo.equipmentList.map { it.toApiUpdateDeviceList() }
else emptyList()
updateDeviceList = dbInfo.equipmentList.filter { dbEquipmentInfo ->
val secondaryDeviceCheckedStatus = dbEquipmentInfo.secondaryDeviceCheckedStatus
val isDuplicateDeviceInUpdatePhase = dbEquipmentInfo.isDeviceUpdateMode
secondaryDeviceCheckedStatus == CHECKED_YES && isDuplicateDeviceInUpdatePhase
}.map { it.toApiUpdateDeviceList() }
I'm building an android app just to show or convert some cripto to USD.. But I dont know how to use and API and get the exact price value of bitcoin(any cripto)...How do I filter the json to get just the right value?
private fun converter(){
val selectedCurrency = findViewById<RadioGroup>(R.id.radioGroup)
val editField = findViewById<EditText>(R.id.edit_field)
val value = editField.text.toString()
if (value.isEmpty() || value == ".")
return
Thread{
//Para here
val url = URL("https://api.coinmarketcap.com/data-api/v3/cryptocurrency/listing?start=1&limit=500")
val conn = url.openConnection() as HttpsURLConnection
try {
val data = conn.inputStream.bufferedReader().readText()
// {"price": 32000.000} what i want to get and idk how
val obj = JSONObject(data)
runOnUiThread{
val res = obj
result.text = res.toString()
result.visibility = View.VISIBLE
}
}finally{
conn.disconnect()
}
}.start()
This is unusuall response where the name of object is the same as the object's ID and at this point I don't really know how to parse this response
"addresses": {
"163492": {
"address_id": "163492",
//more of String variables
},
"166127": {
"address_id": "166127",
//more of String variables
},
"166202": {
"address_id": "166202",
//more of String variables
}
}
this is how my Event model looks like, I'm using room database to save this response later
#Entity
data class Event(
#PrimaryKey(autoGenerate = false)
#SerializedName("id") val id: Int,
#SerializedName("title") val title: String,
#SerializedName("description") val desc: String,
#SerializedName("note") val note: String? = null,
#SerializedName("date") val dateTs: Long,
#SerializedName("begintime") val beginTime: String,
#SerializedName("enddate") val endDate: String,
#SerializedName("endtime") val endTime: String,
#SerializedName("customerid") val customerId: String? = null,
#SerializedName("address_id") val addressId: String? = null,
#SerializedName("pin") val pin: String? = null,
#SerializedName("location") val location: String? = null,
#SerializedName("customerlocation") val customerLocation: String? = null,
#field:TypeConverters(beskidmedia.pl.scanner.room.TypeConverters::class)
#SerializedName("nodes") val nodes: List<Node>? = null,
#SerializedName("closed") val closed: Int,
#SerializedName("type") val type: Int,
#SerializedName("ticketid") val ticketId: String? = null,
#SerializedName("customername") val customerName: String? = null,
#field:TypeConverters(beskidmedia.pl.scanner.room.TypeConverters::class)
#SerializedName("contacts") val contacts: List<Contacts>? = null,
#field:TypeConverters(beskidmedia.pl.scanner.room.TypeConverters::class)
#SerializedName("addresses") val addresses: List<Address>? = null,
#Embedded
#SerializedName("assignments") val assignments: Assignments? = null,
#SerializedName("lastUpdate") val lastUpdate: Long = System.currentTimeMillis()
)
everything beside the addresses part is fine cos I tested it using response with null for addresses, I tried to do deserializer for this but it appears like it don't recognise it, this is how it looks like
class EventDeserializer : JsonDeserializer<Event> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): Event {
json?.asJsonObject!!.let { event ->
val nodes = mutableListOf<Node>()
val contacts = mutableListOf<Contacts>()
val addresses = mutableListOf<Address>()
val net = mutableListOf<Assignment>()
val tv = mutableListOf<Assignment>()
val assignments = Assignments(net, tv)
val netTemp = event.get("assignments").asJsonObject.get("assignments_net").asJsonArray
val tvTemp = event.get("assignments").asJsonObject.get("assignments_tv").asJsonArray
netTemp.forEach { assignment ->
assignment.asJsonObject.let {
net.add(
Assignment(
name = it.get("name").asString,
id = it.get("id").asInt
)
)
}
}
tvTemp.forEach { assignment ->
assignment.asJsonObject.let {
tv.add(
Assignment(
name = it.get("name").asString,
id = it.get("id").asInt
)
)
}
}
val nodesTemp = event.get("nodes").asJsonArray
nodesTemp.forEach { node ->
node.asJsonObject.let {
nodes.add(
Node(
id = it.get("id").asInt,
name = it.get("name").asString,
mac = it.get("mac").asString,
ip = it.get("ip").asString,
location = it.get("location").asString,
netName = it.get("netname").asString
)
)
}
}
val contactsTemp = event.get("contacts").asJsonArray
contactsTemp.forEach { contact ->
contact.asJsonObject.let {
contacts.add(
Contacts(
phone = it.get("phone").asString,
contact = it.get("contact").asString,
name = it.get("name").asString,
type = it.get("type").asString,
typeStr = it.get("typestr").asString
)
)
}
}
val addressesTemp = event.get("addresses").asJsonObject
addressesTemp?.keySet()?.let { names ->
names.forEach { name ->
addressesTemp.get(name).asJsonObject.let {
addresses.add(
Address(
id = it.get("address_id").asString,
name = it.get("location").asString
)
)
}
}
}
return Event(
id = event.get("id").asInt,
title = event.get("title").asString,
desc = event.get("description").asString,
note = event.get("note")?.asString,
dateTs = event.get("date").asLong,
beginTime = event.get("begintime").asString,
endDate = event.get("enddate").asString,
endTime = event.get("endtime").asString,
customerId = event.get("customerid")?.asString,
addressId = event.get("address_id")?.asString,
pin = event.get("pin")?.asString,
location = event.get("location")?.asString,
customerLocation = event.get("customerlocation")?.asString,
nodes = nodes,
closed = event.get("closed").asInt,
type = event.get("type").asInt,
ticketId = event.get("ticketid")?.asString,
customerName = event.get("customername")?.asString,
contacts = contacts,
addresses = addresses,
assignments = assignments
)
}
}
}
and this is how I'm creating gson factory
val gson = GsonBuilder().registerTypeAdapter(Event::class.java, EventDeserializer())
Retrofit
.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(
GsonConverterFactory.create(gson.create())
)
.callbackExecutor(Executors.newSingleThreadExecutor())
and the structure of response looks like this
Call<List<Event>>
but the list always have 1 element and this is artifact of old api that i can't change
Ok, so I figured this out, apparently your deserializer needs to be the exactly the same type as your response, so I added the interceptor that removed excess array that wrapped every response and now deserializer is being ussed as intended.
I'm trying to parse this public Api JSON "https://api.quarantine.country/api/v1/summary/latest"
and the problem starts when I need to parse Object "Region" which is a Map of key String value Object Country. I'm doing this manually on purpose just for practice.
This is my code till now:
private fun writeData(json: String?) {
val jsonObj = JSONObject(json)
val data = jsonObj.getJSONObject("data")
val summary = data.getJSONObject("summary")
val total_casesSummary = summary.getInt("total_cases")
val active_casesSummary = summary.getInt("active_cases")
val deathsSummary = summary.getInt("deaths")
val recoveredSummary = summary.getInt("recovered")
val criticalSummary = summary.getInt("critical")
val testedSummary = summary.getInt("tested")
val death_ratioSummary = summary.getDouble("death_ratio")
val recovery_ratioSummary = summary.getDouble("recovery_ratio")
val summaryObj = ChangeSummary(total_casesSummary,
active_casesSummary,
deathsSummary,
recoveredSummary,
criticalSummary,
testedSummary,
death_ratioSummary,
recovery_ratioSummary)
val change = data.getJSONObject("change")
val total_casesChange = data.getInt("total_cases")
val active_casesChange = data.getInt("active_cases")
val deathsChange = data.getInt("deaths")
val recoveredChange = data.getInt("recovered")
val criticalChange = data.getInt("critical")
val testedChange = data.getInt("tested")
val death_ratioChange = data.getDouble("death_ratio")
val recovery_ratioChange = data.getDouble("recovery_ratio")
val changeObj = ChangeSummary(total_casesChange,
active_casesChange,
deathsChange,
recoveredChange,
criticalChange,
testedChange,
death_ratioChange,
recovery_ratioChange)
val regions = data.getJSONObject("regions")
}
and there problem starts here when I need to read countries from object regions:
"regions":{
"usa":{
"name":"USA",
"iso3166a2":"US",
"iso3166a3":"USA",
"iso3166numeric":"",
"total_cases":34219271,
"active_cases":5440268,
"deaths":612532,
"recovered":28166471,
"critical":5259,
"tested":487505878,
"death_ratio":0.017900205997959454,
"recovery_ratio":0.8231172136893273,
"change":{
"total_cases":10304,
"active_cases":-36393,
"deaths":179,
"recovered":46518,
"death_ratio":-1.5913145237633763e-7,
"recovery_ratio":0.0011118897635858938
}
},
"india":{
"name":"India",
"iso3166a2":"IN",
"iso3166a3":"IND",
"iso3166numeric":"",
"total_cases":28996949,
"active_cases":1308806,
"deaths":351344,
"recovered":27336799,
"critical":8944,
"tested":366334111,
"death_ratio":0.01211658509314204,
"recovery_ratio":0.9427474249101173,
"change":{
"total_cases":87345,
"active_cases":-100842,
"deaths":2115,
"recovered":186072,
"death_ratio":3.655106707928235e-5,
"recovery_ratio":0.0035880023182339738
}
},
I want to save data acquired from Volley, But lambda used in VolleyRequest function(which gets json data from server) blocks it.
How should I change local variable that is in outside of lambda?
Thanks in advance.
class ConDataforReturn( val title:String , val imgDataList: ArrayList<ConImgData>)
fun getConData(context: Context, idx : String):ConDataforReturn{
val params = HashMap<String,String>()
var cd = arrayListOf<ConImgData>()
var title =""
params.put("package_idx",idx)
Log.e("idx size",idx.length.toString())
VolleyRequest(context,params,"https://dccon.dcinside.com/index/package_detail") { response ->
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
Log.d("title",title)//Prints right data
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
cd.add(ConImgData(v.getString("title"), v.getString("ext"), v.getString("path")))
}
}
return ConDataforReturn(title,cd)//returns ConDataforReturn("",arrayListOf<ConImgData>())
}
Here the the code from were you are calling this method
getConData(this, "id") { condata ->
}
Now, your method look like this,
fun getConData(context: Context, idx : String, returnConData : (condata : ConDataforReturn) -> Unit){
val params = HashMap<String,String>()
var cd = arrayListOf<ConImgData>()
var title =""
params.put("package_idx",idx)
Log.e("idx size",idx.length.toString())
VolleyRequest(context,params,"https://dccon.dcinside.com/index/package_detail") { response ->
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
Log.d("title",title)//Prints right data
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
cd.add(ConImgData(v.getString("title"), v.getString("ext"), v.getString("path")))
}
returnConData(ConDataforReturn(title,cd)) //returns ConDataforReturn("",arrayListOf<ConImgData>())
}
}