前提
Androidにおけるjsonのパーサーライブラリの鉄板といえばGsonですが(個人調べ)、このライブラリはKotlinでも問題なく(個人調べ)利用することができます。
User.kt
data class User(
val userId: String,
val username: String
)
MainClass.kt
val user = Gson().fromJson(json, User::class.java)
keyが完全に不定なjson
mediumは投稿関連のAPIしか提供されていませんが、各URLにformat=json
のクエリを入れることでjsonが返ってくるようになるので、これをGsonでパースすることができます。
サンプルURL: https://medium.com/japan?format=json
top.json
])}while(1);</x>{"success":true,"payload":{"collection":{"id":"ee897b6da065","name":"Medium Japan","slug":"japan","tags":["PUBLICATIONS","JAPANESE","MEDIUM JAPAN","日本語"],"creatorId":"cd5018cebde7","description":"Medium 公式の日本語専用パブリケーションです。","shortDescription":"Medium 公式の日本語専用パブリケーションです。","image":{"imageId":"1*etUthOXG-BrZm25K7wEcgA.png","filter":"","backgroundSize":"","originalWidth":500,"originalHeight":500,"strategy":"resample","height":0,"width":0},"metadata":{"followerCount":4101,"activeAt":1487168607377},"virtuals":{"permissions":{"canPublish":false,"canPublishAll":false,"canRepublish":false,"canRemove":false,"canManageAll":false,"canSubmit":false,"canEditPosts":false,"canAddWriters":false,"canViewStats":false,"canSendNewsletter":false,"canViewLockedPosts":false,"canViewCloaked":false,"canEditOwnPosts":false,"canBeAssignedAuthor":false},"isSubscribed":false,"isNewsletterSubscribed":false,"memberOfMembershipPlanId":""},"logo":{"imageId":"1*etUthOXG-BrZm25K7wEcgA.png","filter":"","backgroundSize":"","originalWidth":500,"originalHeight":500,"strategy":"resample","height":0,"width":0},"twitterUsername":"MediumJapan","facebookPageName":"MediumJapan","sections":[{"type":2,"collectionHeaderMetadata":{"title":"Medium Japan","description":"Medium の公式日本語パブリケーションへようこ
// 省略
ちなみに先頭にXSS対策で付いている(と思われる) ])}while(1);</x>{
を削除した上でパースする必要があります。
ただし、このjsonはUser情報やPost情報のリストが配列ではなく、各IDをkeyとしたオブジェクトで登録されています。これだと @SerializedName(alternate = {})
でもパースは事実上不可能です。
top.json
{
"payload":{
"references":{
"User":{
"1106b2cd94a5":{
"userId":"1106b2cd94a5",
"username":"rayyama"
},
"c78a7314d9a5":{
"userId":"c78a7314d9a5",
"username":"SayakaNogawa",
},
"6673db351714":{
"userId":"6673db351714",
"username":"mach"
}
}
}
}
}
※ 必要な部分を抜粋
Mapとしてjsonをパースする
ということでどうすれば取れるかを考えたのですが、keyの値は不定でも文字列型であることは一定しているので、Mapとして取得できるみたいです。
User.kt
data class Payload(
val references: References
)
data class References(
@SerializedName("User") val users: Map<*, User>
)
data class User(
val userId: String,
val username: String
)
MainClass.kt
val users = Gson().fromJson(json, Payload::class.java)
// 各ユーザーのuserIdを出力
for ((_, user) in users.payload.references.users) {
Log.d(TAG, user.userId)
}
今回はKotlinでやってみましたが、おそらくjavaも同じ要領で Map<String, User>
でいけるんじゃないかと思います。
ご指摘等あれば編集リクエストまたはコメントにてお願いします。