英文:
Parse JSON Array without Key in Android using Retrofit and Kotlin
问题
I'm here to help with your translation request. Here's the translated content you provided:
我一直在开发一个Android应用程序,我一直在处理API调用/响应等问题。问题在于我收到的API响应已经发生了变化,我无法找到序列化和打包的方法。
这是来自API的旧响应:
[
{
"msg": "此时间段无可用数据:2022-11-14 11:00:00 和 2022-11-14 11:15:00"
},
{
"datetime": "2022-11-14 11:15:00",
"avg_temp": 27.59265899658203,
"min_temp": 27.59265899658203,
"max_temp": 27.59265899658203,
"open_temp": 27.59265899658203,
"close_temp": 27.59265899658203
},
{
"datetime": "2022-11-14 11:30:00",
"avg_temp": 27.59265899658203,
"min_temp": 27.59265899658203,
"max_temp": 27.59265899658203,
"open_temp": 27.59265899658203,
"close_temp": 27.59265899658203
}
]
API响应变成了这样:
[
[
1668413700,
-99,
29,
27.59,
27.59,
27.59,
27.59,
27.59
],
[
1668414600,
-99,
29,
27.59,
27.59,
27.59,
27.59,
27.59
]
]
因此,我已经创建了这样的数据类:
@Parcelize
data class TRA(
@SerializedName("datetime")
val datetime: Long?,
@SerializedName("pred")
val pred: Float?,
@SerializedName("sensor")
val sensor: Int?,
@SerializedName("average")
val average: Float?,
@SerializedName("min")
val min: Float?,
@SerializedName("max")
val max: Float?,
@SerializedName("open")
val open: Float?,
@SerializedName("close")
val close: Float?,
@SerializedName("msg")
val msg: String?
): Parcelable
我还有这样的Repository类,并对其进行了修改以适应新的API响应:
suspend fun uploadId(request: TextRecognitionRequest): List
return try {
val response = api.uploadSensorId(request = request)
val jsonArray = JSONArray(response)
val resultList = mutableListOf
for (i in 0 until jsonArray.length()) {
val json = jsonArray.getJSONArray(i)
val item = TemperatureResponseAggregation(
datetime = json.optInt(0),
pred = json.optDouble(1).toFloat(),
sensor = json.optInt(2),
average = json.optDouble(3).toFloat(),
min = json.optDouble(4).toFloat(),
max = json.optDouble(5).toFloat(),
open = json.optDouble(6).toFloat(),
close = json.optDouble(7).toFloat(),
)
resultList.add(item)
}
resultList
} catch (e: Exception) {
e.printStackTrace()
null
}
}
这是我的MainActivityViewModel类:
@HiltViewModel
class MainActivityViewModel @Inject constructor(
private val repository: CameraRepository
) : ViewModel() {
private val _sensorResponse = MutableLiveData<List<TRA>>()
val sensorResponse: LiveData<List<TRA>> = _sensorResponse
fun uploadSensorId(request: TextRecognitionRequest) {
viewModelScope.launch {
_sensorResponse.postValue(repository.uploadSensorId(request))
}
}
}
顺便说一下,我像这样使用了Retrofit:
@Provides
@Singleton
fun provideCameraApi(okHttpClient: OkHttpClient): CameraApi {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(CameraApi::class.java)
}
最后,在我的主活动中,我有一个将这些响应数据写入图表的函数,它如下所示:
```plaintext
private fun lineChartForDataObservation() {
viewModel.sensorResponse.observe(this) { response ->
response?.let { safeResponse ->
val values = arrayListOf<Float>()
val valuesPred = arrayListOf<Float>()
val valuesClose = arrayListOf<Float>()
val valuesOpen = arrayListOf<Float>()
val valuesMax = arrayListOf<Float>()
val valuesMin = arrayListOf<Float>()
dates = arrayListOf()
val sensors = arrayListOf<Int>()
for (item in safeResponse) {
item.datetime?.let { dates.add(it.toString()) }
item.pred?.let { valuesPred.add(it) }
item.average?.let { values.add(it) }
item.open?.let { valuesOpen.add(it) }
item.close?.let { valuesClose.add(it) }
item.min?.let { valuesMin.add(it) }
item.max?.let { valuesMax.add(it) }
}
chartModels.add(
AASeriesElement()
.name(sensors.component1().toString())
.data(values.toTypedArray())
.allowPointSelect(true)
.dashStyle(AAChartLineDashStyleType.Solid)
)
drawChart()
} ?: run {
Toast.makeText(this, "出了点问题!", Toast.LENGTH_LONG).show()
startActivity(Intent(this, OpenCameraActivity::class.java))
}
}
}
我已经努力并搜索了解决方法,但找不到有用的或有帮助的东西,所以请帮助我了解如何完成这项任务,如果我解释问题不清楚,对此我感到抱歉,我还是个新手。
Please let me know if you need any further assistance!
<details>
<summary>英文:</summary>
I've been working on an android app and I've been struggling with api calls/responses etc. and the problem is the api response I received and serialized/parcelized it's been changed and I couldn't find a way to serialize and parcelize.
This is the old response from api:
[
{
"msg": "No data available for this time period: 2022-11-14 11:00:00 and 2022-11-14 11:15:00"
},
{
"datetime": "2022-11-14 11:15:00",
"avg_temp": 27.59265899658203,
"min_temp": 27.59265899658203,
"max_temp": 27.59265899658203,
"open_temp": 27.59265899658203,
"close_temp": 27.59265899658203
},
{
"datetime": "2022-11-14 11:30:00",
"avg_temp": 27.59265899658203,
"min_temp": 27.59265899658203,
"max_temp": 27.59265899658203,
"open_temp": 27.59265899658203,
"close_temp": 27.59265899658203
}
]
Api response change into this:
[
[
1668413700,
-99,
29,
27.59,
27.59,
27.59,
27.59,
27.59
],
[
1668414600,
-99,
29,
27.59,
27.59,
27.59,
27.59,
27.59
]
]
and so I've already created a data class like this:
@Parcelize
data class TRA(
@SerializedName("datetime")
val datetime: Long?,
@SerializedName("pred")
val pred: Float?,
@SerializedName("sensor")
val sensor: Int?,
@SerializedName("average")
val average: Float?,
@SerializedName("min")
val min: Float?,
@SerializedName("max")
val max: Float?,
@SerializedName("open")
val open: Float?,
@SerializedName("close")
val close: Float?,
@SerializedName("msg")
val msg: String?
):Parcelable
and I've Repository class like this and I've modified like this to work with new api response:
suspend fun uploadId(request: TextRecognitionRequest): List<TRA>? {
return try {
val response = api.uploadSensorId(request = request)
val jsonArray = JSONArray(response)
val resultList = mutableListOf<TRA>()
for (i in 0 until jsonArray.length()) {
val json = jsonArray.getJSONArray(i)
val item = TemperatureResponseAggregation(
datetime = json.optInt(0),
pred = json.optDouble(1).toFloat(),
sensor = json.optInt(2),
average = json.optDouble(3).toFloat(),
min = json.optDouble(4).toFloat(),
max = json.optDouble(5).toFloat(),
open = json.optDouble(6).toFloat(),
close = json.optDouble(7).toFloat(),
)
resultList.add(item)
}
resultList
} catch (e: Exception) {
e.printStackTrace()
null
}
}
this is my MainActivityViewModel class:
@HiltViewModel
class MainActivityViewModel @Inject constructor(
private val repository: CameraRepository
) : ViewModel() {
private val _sensorResponse = MutableLiveData<List<TRA>>()
val sensorResponse: LiveData<List<TRA>> = _sensorResponse
fun uploadSensorId(request: TextRecognitionRequest) {
viewModelScope.launch {
_sensorResponse.postValue(repository.uploadSensorId(request))
}
}
}
I'm using retrofit by the way like this:
@Provides
@Singleton
fun provideCameraApi(okHttpClient: OkHttpClient): CameraApi {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(CameraApi::class.java)
}
Finally in my main activity I have a function that writes these response datas into the chart it goes like this:
private fun lineChartForDataObservation() {
viewModel.sensorResponse.observe(this) { response ->
response?.let { safeResponse ->
val values = arrayListOf<Float>()
val valuesPred = arrayListOf<Float>()
val valuesClose = arrayListOf<Float>()
val valuesOpen = arrayListOf<Float>()
val valuesMax = arrayListOf<Float>()
val valuesMin = arrayListOf<Float>()
dates = arrayListOf()
val sensors = arrayListOf<Int>()
for (item in safeResponse) {
item.datetime?.let { dates.add(it.toString()) }
item.pred?.let { valuesPred.add(it) }
item.average?.let { values.add(it) }
item.open?.let { valuesOpen.add(it) }
item.close?.let { valuesClose.add(it) }
item.min?.let { valuesMin.add(it) }
item.max?.let { valuesMax.add(it) }
}
chartModels.add(
AASeriesElement()
.name(sensors.component1().toString())
.data(values.toTypedArray())
.allowPointSelect(true)
.dashStyle(AAChartLineDashStyleType.Solid)
)
drawChart()
} ?: run {
Toast.makeText(this, "Something went wrong!", Toast.LENGTH_LONG).show()
startActivity(Intent(this, OpenCameraActivity::class.java))
}
}
}
I've tried and search for a solution for this but couldn't find anything useful or helpful so please I want to learn how can I do this task, and if I explained my problem badly sorry about it I'm still a newbie at this kind of things.
**SOLUTION**
I made it worked guys the problem was in my api interface I've changed to Object to Array<Array<Double>> it works that way now, thank you for suggestions and helps. I really appreciated
@POST("....")
suspend fun test(
@Header("Accept") header1: String = "....",
@Header("User-Agent") header2: String = "....",
@Header("Connection") header5: String= ".....",
@Body request: .....,
) : Array<Array<Double>>
</details>
# 答案1
**得分**: 0
This is not going to work with the "new api response" since your new api response is an array of arrays of floats.
You'd need something like:
for (i in 0 until jsonArray.length()) {
val jsonArrayOfFloats = jsonArray.getJSONArray(i)
// Parse jsonArrayOfFloats and do something with values
<details>
<summary>英文:</summary>
> and I've Repository class like this and I've modified like this to work with new api response:
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
This is not going to work with the "new api response" since your new api response is an array of arrays of floats.
You'd need something like:
for (i in 0 until jsonArray.length()) {
val jsonArrayOfFloats = jsonArray.getJSONArray(i)
// Parse jsonArrayOfFloats and do something with values
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论