有没有办法直接在界面中解析改造响应,用函数解析响应
Posted
技术标签:
【中文标题】有没有办法直接在界面中解析改造响应,用函数解析响应【英文标题】:Is there a way to parse the retrofit response directly in the interface and parse the response with a function 【发布时间】:2021-10-12 19:00:48 【问题描述】:我对 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
现在我的问题是,我是否可以直接在 NasaApiService 接口中解析数据并取回我创建的数据类型 asteroid 的列表,而不是在获取响应后解析 viewModel 中的数据。我一直在寻找,但找不到它是否在那里。如果你想知道 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
【问题讨论】:
为什么不使用data class
和gson converter factory
?
在使用 Retrofit 时几乎支持解析为 JSON 或自定义对象/数据类。查看改造文档并查找:“改造配置”>“转换器”。这里有很多关于 SO 的例子,例如:***.com/questions/60754180/…
【参考方案1】:
在您的模块级 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
【讨论】:
以上是关于有没有办法直接在界面中解析改造响应,用函数解析响应的主要内容,如果未能解决你的问题,请参考以下文章