I am very new to kotlin and I am working on a Kotlin app and in it I am using retrofit to parse data from an api. Now I get the data back as a json object and because it is not a list I decided to use the scalers converter to get the data back as a string. Here is my ApiService file:
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)
}
}
Now to convert this into the json I want I have a function that can change this string data into the json data I want. And I use it in the viewModel when getting the result. Here:
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
}
}
Now my question is whether instead of parsing the data in the viewModel after getting the response could I parse the data directly in the NasaApiService Interface and get back a list of the data type asteroid I created. I kept searching but couldnt find if it was there or not there. If you are wondering what the json response is here you go:
{
"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,
...
From this data I actually only need all the data from the near earth objects list. Which the function can do as long as I give it the string data it needs. Here is the function that I use to parse so you can try and understand more.
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
}