如何使用 Retrofit2 编写 POJO 以从 JSON 中获取对象内的特定数组?
How to write POJOs to get specific array inside an object from JSON using Retrofit2?
嗯,我需要做一个任务:新闻分页列表。
为此,我从 googlesample/architecthurecomponents/PagingWithNetworkSample 中抽取了一个样本并遇到了这个问题。问题是关于 google 样本中解析 JSON 文件的代码。
JSON url: https://www.reddit.com/r/androiddev/hot.json
POJO 文件:
@Entity(tableName = "posts",
indices = [Index(value = ["subreddit"], unique = false)])
data class RedditPost(
@PrimaryKey
@SerializedName("name")
val name: String,
@SerializedName("title")
val title: String,
@SerializedName("score")
val score: Int,
@SerializedName("author")
val author: String,
@SerializedName("subreddit") // this seems mutable but fine for a demo
@ColumnInfo(collate = ColumnInfo.NOCASE)
val subreddit: String,
@SerializedName("num_comments")
val num_comments: Int,
@SerializedName("created_utc")
val created: Long,
val thumbnail: String?,
val url: String?) {
// to be consistent w/ changing backend order, we need to keep a data like this
var indexInResponse: Int = -1
}
这是一个 api 接口:
interface RedditApi {
@GET("/r/{subreddit}/hot.json")
fun getTop(
@Path("subreddit") subreddit: String,
@Query("limit") limit: Int): Call<ListingResponse>
@GET("/r/{subreddit}/hot.json")
fun getTopAfter(
@Path("subreddit") subreddit: String,
@Query("after") after: String,
@Query("limit") limit: Int): Call<ListingResponse>
@GET("/r/{subreddit}/hot.json")
fun getTopBefore(
@Path("subreddit") subreddit: String,
@Query("before") before: String,
@Query("limit") limit: Int): Call<ListingResponse>
class ListingResponse(val data: ListingData)
class ListingData(
val children: List<RedditChildrenResponse>,
val after: String?,
val before: String?
)
data class RedditChildrenResponse(val data: RedditPost)
companion object {
private const val BASE_URL = "https://www.reddit.com/"
fun create(): RedditApi = create(HttpUrl.parse(BASE_URL)!!)
fun create(httpUrl: HttpUrl): RedditApi {
val logger = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
Log.d("API", it)
})
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(httpUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(RedditApi::class.java)
}
}
}
问题是:api 请求如何准确地找到我们需要的内容,一个 children: [...],代表一个帖子列表?因为 children: [...] 驻留在对象内部,并且在代码中我们没有带有 @Serialized("children") 字段的 POJO。仅用于儿童内部物品的 pojo:[...]。我试图实现这种特定于我的 json 的方法,但它 returns 是一个空值。
感谢大家的帮助。
如果 POJO 中的字段名称与 JSON 中的字段名称相同,则不必添加 @SerializedName
注释。这就是为什么 class ListingResponse(val data: ListingData)
可以映射到
{
"kind": "Listing",
"data": ...
}
嗯,我需要做一个任务:新闻分页列表。 为此,我从 googlesample/architecthurecomponents/PagingWithNetworkSample 中抽取了一个样本并遇到了这个问题。问题是关于 google 样本中解析 JSON 文件的代码。
JSON url: https://www.reddit.com/r/androiddev/hot.json
POJO 文件:
@Entity(tableName = "posts",
indices = [Index(value = ["subreddit"], unique = false)])
data class RedditPost(
@PrimaryKey
@SerializedName("name")
val name: String,
@SerializedName("title")
val title: String,
@SerializedName("score")
val score: Int,
@SerializedName("author")
val author: String,
@SerializedName("subreddit") // this seems mutable but fine for a demo
@ColumnInfo(collate = ColumnInfo.NOCASE)
val subreddit: String,
@SerializedName("num_comments")
val num_comments: Int,
@SerializedName("created_utc")
val created: Long,
val thumbnail: String?,
val url: String?) {
// to be consistent w/ changing backend order, we need to keep a data like this
var indexInResponse: Int = -1
}
这是一个 api 接口:
interface RedditApi {
@GET("/r/{subreddit}/hot.json")
fun getTop(
@Path("subreddit") subreddit: String,
@Query("limit") limit: Int): Call<ListingResponse>
@GET("/r/{subreddit}/hot.json")
fun getTopAfter(
@Path("subreddit") subreddit: String,
@Query("after") after: String,
@Query("limit") limit: Int): Call<ListingResponse>
@GET("/r/{subreddit}/hot.json")
fun getTopBefore(
@Path("subreddit") subreddit: String,
@Query("before") before: String,
@Query("limit") limit: Int): Call<ListingResponse>
class ListingResponse(val data: ListingData)
class ListingData(
val children: List<RedditChildrenResponse>,
val after: String?,
val before: String?
)
data class RedditChildrenResponse(val data: RedditPost)
companion object {
private const val BASE_URL = "https://www.reddit.com/"
fun create(): RedditApi = create(HttpUrl.parse(BASE_URL)!!)
fun create(httpUrl: HttpUrl): RedditApi {
val logger = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
Log.d("API", it)
})
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(httpUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(RedditApi::class.java)
}
}
}
问题是:api 请求如何准确地找到我们需要的内容,一个 children: [...],代表一个帖子列表?因为 children: [...] 驻留在对象内部,并且在代码中我们没有带有 @Serialized("children") 字段的 POJO。仅用于儿童内部物品的 pojo:[...]。我试图实现这种特定于我的 json 的方法,但它 returns 是一个空值。
感谢大家的帮助。
如果 POJO 中的字段名称与 JSON 中的字段名称相同,则不必添加 @SerializedName
注释。这就是为什么 class ListingResponse(val data: ListingData)
可以映射到
{
"kind": "Listing",
"data": ...
}