Разбор массива JSON без ключа в Android с использованием Retrofit и Kotlin

Я работаю над приложением для Android, и я боролся с вызовами/ответами API и т. д., и проблема заключается в том, что ответ API, который я получил и сериализовал/парцеллировал, был изменен, и я не мог найти способ сериализовать и разделить .

Это старый ответ 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 меняется на это:

[
      [
          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

и у меня есть такой класс репозитория, и я изменил его для работы с новым ответом API:

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
        }
    }

это мой класс 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))
        }
    }

}

Я использую модификацию таким образом:

    @Provides
    @Singleton
    fun provideCameraApi(okHttpClient: OkHttpClient): CameraApi {
        return Retrofit.Builder()
            .baseUrl(Constants.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(CameraApi::class.java)
    }

Наконец, в моей основной деятельности у меня есть функция, которая записывает эти данные ответа в диаграмму, она выглядит следующим образом:

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))
            }
        }
    }

Я пробовал и искал решение для этого, но не смог найти ничего полезного или полезного, поэтому, пожалуйста, я хочу узнать, как я могу выполнить эту задачу, и если я плохо объяснил свою проблему, извините за это, я все еще новичок в такого рода вещи.

РЕШЕНИЕ

Я заставил это работать, ребята, проблема была в моем интерфейсе API, который я изменил на Object to Array<Array>, теперь он работает так, спасибо за предложения и помощь. я очень ценю

    @POST("....")
suspend fun test(
    @Header("Accept") header1: String = "....",
    @Header("User-Agent") header2: String = "....",

    @Header("Connection") header5: String= ".....",
    @Body request: .....,
) : Array<Array<Double>>
0
0
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

и у меня есть такой класс репозитория, и я изменил его для работы с новым ответом API:

for (i in 0 until jsonArray.length()) {
    val jsonObject = jsonArray.getJSONObject(i)

Это не будет работать с «новым ответом API», поскольку ваш новый ответ API представляет собой массив массивов с плавающей запятой.

Вам понадобится что-то вроде:

for (i in 0 until jsonArray.length()) {
    val jsonArrayOfFloats = jsonArray.getJSONArray(i)
    // Parse jsonArrayOfFloats and do something with values

насколько я понимаю, мне нужно изменить класс репозитория и не трогать другие, которые я упомянул, верно? Кстати, я извиняюсь, если мой вопрос звучит немного глупо, я все еще учусь таким вещам.

Kaljal 10.04.2023 22:43

Предполагая, что значения с плавающей запятой в массивах соответствуют ранее названным значениям, тогда да, вам нужно всего лишь изменить функцию uploadId, чтобы правильно проанализировать данные и создать объекты TRA. Все остальное должно быть в состоянии остаться прежним.

dominicoder 10.04.2023 23:01

Я внес некоторые коррективы, теперь я собираюсь отредактировать часть вопроса uploadId, можете ли вы проверить это также, потому что я думаю, что сделал что-то не так, и это не сработало

Kaljal 10.04.2023 23:14

Хорошо, но вам придется уточнить, что означает «это не сработало».

dominicoder 10.04.2023 23:27

извините, да, поэтому, когда я применяю эти изменения к классу репозитория, функция lineChartForDataObservation в основном действии должна отображать эти данные на линейной диаграмме, но это не так, и из-за этого приложения происходит сбой

Kaljal 10.04.2023 23:51

«приложение вылетает» не поясняет, что означает «оно не сработало». Пожалуйста, отладьте свое приложение, чтобы определить, что вызывает его сбой. Тогда сделай так, чтобы этого не было.

dominicoder 11.04.2023 02:26

Я помещаю некоторый Log.e для отладки в «uploadId», и код запускает блок catch, и сообщение об исключении выглядит так: «Произошло исключение: java.lang.IllegalStateException: Ожидается BEGIN_OBJECT, но был BEGIN_ARRAY в строке 2, столбце 6, путь $[0] "

Kaljal 11.04.2023 02:48

Это указывает на то, что ваш код написан для анализа объекта JSON («Ожидаемый BEGIN_OBJECT»), но данные на самом деле являются массивом («но был BEGIN_ARRAY»). Убедитесь, что код, который вы пишете для синтаксического анализа, соответствует входной структуре json.

dominicoder 11.04.2023 05:41

Как мне это сделать, что мне нужно изменить, чтобы разобрать его, класс данных? класс репозитория?

Kaljal 11.04.2023 12:03

Вам не нужны данные или классы репозитория — исключение сообщает вам строку, которая была проанализирована неправильно. Вы пытались getJSONObject когда это должно было быть getJSONArray

dominicoder 11.04.2023 16:26

Я обновил его до getJsonArray, вы можете увидеть обновленный код выше, но он по-прежнему дает мне то же исключение, он запускает только блок catch

Kaljal 11.04.2023 17:01

Выложите полную трассировку стека.

dominicoder 11.04.2023 17:45

Я заставил это работать, проблема была в моем интерфейсе API. Я изменил Object на Array<Array<Double>>, теперь он работает так, спасибо за помощь

Kaljal 11.04.2023 18:24

Другие вопросы по теме