Есть ли способ проанализировать ответ на модификацию непосредственно в интерфейсе и проанализировать ответ с помощью функции

avatar
KidCoder
9 августа 2021 в 01:53
146
1
1

Я новичок в kotlin, работаю над приложением Kotlin и использую в нем модификацию для анализа данных из API. Теперь я получаю данные обратно в виде объекта json, и, поскольку это не список, я решил использовать преобразователь скейлеров, чтобы вернуть данные в виде строки. Вот мой файл ApiService:

    private val retrofit = Retrofit.Builder()
        .addConverterFactory(ScalarsConverterFactory.create())
        .baseUrl(BASE_URL)
        .build()

    interface NasaApiService {
        @GET("neo/rest/v1/feed?api_key=$API_KEY")
        fun getProperties():
                Call<String>
    }

    object NasaApi {
        val retrofitService : NasaApiService by lazy {
            retrofit.create(NasaApiService::class.java)
        }
    }

Теперь, чтобы преобразовать это в json, который мне нужен, у меня есть функция, которая может преобразовать эти строковые данные в нужные мне данные json. И я использую его во viewModel при получении результата. Здесь:

    class MainViewModel : ViewModel() {

        private val _asteroids = MutableLiveData<List<Asteroid>>()
        val asteroid: LiveData<List<Asteroid>> get() = _asteroids

        private val _navigateToAsteroidDetails = MutableLiveData<Long>()
        val navigateToAsteroidDetails
            get() = _navigateToAsteroidDetails

        init {
            NasaApi.retrofitService.getProperties().enqueue( object: Callback<String> {
                override fun onResponse(call: Call<String>  response: Response<String>) {
                    _asteroids.value = response.body()?.let { parseAsteroidsJsonResult(it) }
                }

                override fun onFailure(call: Call<String>  t: Throwable) {
                    TODO("Not yet implemented")
                }
            })
        }

        fun onAsteroidItemClicked(id: Long) {
            _navigateToAsteroidDetails.value = id
        }

        fun onAsteroidItemDetailsNavigated() {
            _navigateToAsteroidDetails.value = null
        }
    }

Теперь мой вопрос заключается в том, могу ли я вместо анализа данных в viewModel после получения ответа проанализировать данные непосредственно в интерфейсе NasaApiService и получить обратно список созданных мной астероидов типа данных. Я продолжал искать, но не мог найти, есть он там или нет. Если вам интересно, что ответ json здесь, вы идете:

    {
    "links": {
        "next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-08-16&end_date=2021-08-23&detailed=false&api_key=dj906WfMa1KJzZ0d9fY5KdYE45ZUQniVdptWBd3r",
        "prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-08-02&end_date=2021-08-09&detailed=false&api_key=dj906WfMa1KJzZ0d9fY5KdYE45ZUQniVdptWBd3r",
        "self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-08-09&end_date=2021-08-16&detailed=false&api_key=dj906WfMa1KJzZ0d9fY5KdYE45ZUQniVdptWBd3r"
    },
    "element_count": 80,
    "near_earth_objects": {
        "2021-08-11": [
        {
            "links": {
            "self": "http://www.neowsapp.com/rest/v1/neo/3092269?api_key=dj906WfMa1KJzZ0d9fY5KdYE45ZUQniVdptWBd3r"
            },
            "id": "3092269",
            "neo_reference_id": "3092269",
            "name": "(2000 PN8)",
            "nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3092269",
            "absolute_magnitude_h": 22.1,
            "estimated_diameter": {
            "kilometers": {
                "estimated_diameter_min": 0.1010543415,
                "estimated_diameter_max": 0.2259643771
            },
            "meters": {
                "estimated_diameter_min": 101.054341542,
                "estimated_diameter_max": 225.9643771094
            },
            "miles": {
                "estimated_diameter_min": 0.0627922373,
                "estimated_diameter_max": 0.140407711
            },
            "feet": {
                "estimated_diameter_min": 331.5431259047,
                "estimated_diameter_max": 741.3529669956
            }
            },
            "is_potentially_hazardous_asteroid": false,
            "close_approach_data": [
            {
                "close_approach_date": "2021-08-11",
                "close_approach_date_full": "2021-Aug-11 15:22",
                "epoch_date_close_approach": 1628695320000,
                "relative_velocity": {
                "kilometers_per_second": "13.3546688941",
                "kilometers_per_hour": "48076.8080188273",
                "miles_per_hour": "29873.0588492541"
                },
                "miss_distance": {
                "astronomical": "0.0914372304",
                "lunar": "35.5690826256",
                "kilometers": "13678814.906539248",
                "miles": "8499621.4502397024"
                },
                "orbiting_body": "Earth"
            }
            ],
            "is_sentry_object": false
        },
        {
            "links": {
            "self": "http://www.neowsapp.com/rest/v1/neo/3297182?api_key=dj906WfMa1KJzZ0d9fY5KdYE45ZUQniVdptWBd3r"
            },
            "id": "3297182",
            "neo_reference_id": "3297182",
            "name": "(2005 UE1)",
            "nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3297182",
            "absolute_magnitude_h": 26.2,
            "estimated_diameter": {
            "kilometers": {
                "estimated_diameter_min": 0.0152951935,
                "estimated_diameter_max": 0.0342010925
            },
            "meters": {
                "estimated_diameter_min": 15.2951935344,
                "estimated_diameter_max": 34.201092472
            },
            "miles": {
                "estimated_diameter_min": 0.0095039897,
                "estimated_diameter_max": 0.021251567
            },
            "feet": {
                "estimated_diameter_min": 50.1810827555,
                "estimated_diameter_max": 112.2083122258
            }
            },
            "is_potentially_hazardous_asteroid": false,
            ...

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

        fun parseAsteroidsJsonResult(response: String): ArrayList<Asteroid> {
        val jsonResult = JSONObject(response.toString())
        val nearEarthObjectsJson = jsonResult.getJSONObject("near_earth_objects")

        val asteroidList = ArrayList<Asteroid>()

        val nextSevenDaysFormattedDates = getNextSevenDaysFormattedDates()
        for (formattedDate in nextSevenDaysFormattedDates) {
            val dateAsteroidJsonArray = nearEarthObjectsJson.getJSONArray(formattedDate)

            for (i in 0 until dateAsteroidJsonArray.length()) {
                val asteroidJson = dateAsteroidJsonArray.getJSONObject(i)
                val id = asteroidJson.getLong("id")
                val codename = asteroidJson.getString("name")
                val absoluteMagnitude = asteroidJson.getDouble("absolute_magnitude_h")
                val estimatedDiameter = asteroidJson.getJSONObject("estimated_diameter")
                    .getJSONObject("kilometers").getDouble("estimated_diameter_max")

                val closeApproachData = asteroidJson
                    .getJSONArray("close_approach_data").getJSONObject(0)
                val relativeVelocity = closeApproachData.getJSONObject("relative_velocity")
                    .getDouble("kilometers_per_second")
                val distanceFromEarth = closeApproachData.getJSONObject("miss_distance")
                    .getDouble("astronomical")
                val isPotentiallyHazardous = asteroidJson
                    .getBoolean("is_potentially_hazardous_asteroid")

                val asteroid = Asteroid(id, codename, formattedDate, absoluteMagnitude,
                    estimatedDiameter, relativeVelocity, distanceFromEarth, isPotentiallyHazardous)
                asteroidList.add(asteroid)
            }
        }

        return asteroidList
    }
Источник
USMAN osman
9 августа 2021 в 07:01
0

почему бы не использовать data class с gson converter factory?

Daan
9 августа 2021 в 07:12
0

Синтаксический анализ в JSON или пользовательский класс объектов/данных поддерживается в значительной степени из коробки при использовании Retrofit. Просмотрите документацию по модернизации и найдите: «Конфигурация модернизации» > «Преобразователи». Здесь много примеров на SO, например: coderhelper.com/questions/60754180/…

Ответы (1)

avatar
nowavewater
9 августа 2021 в 10:17
0

В вашем файле gradle на уровне модуля импортируйте следующие зависимости:

implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

Объявить класс данных ответа следующим образом:

data class ExampleResponse (
    @SerializedName("links")
    val linkes: String? = null
)

Добавить GsonConverterFactory в экземпляр Retrofit:

Retrofit.Builder()
    .baseUrl("https://example.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

Наконец объявить интерфейс:

interface ExampleApiService {
    @GET("news")
    fun getNews(): ExampleResponse
}