最近正在用纯Scala来写android 的APP,踩了不少的坑,为了解析个json都折腾了半天,之前打算用gson,fastJson的没成功,后来用了spray-json,下面总结一下
环境搭建
最顶层的build.gradle
文件中添加scala插件的依赖路径和地址,如下所示
buildscript {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.github.xingda920813:gradle-android-scala-plugin:android-gradle-2.3.0'
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
在Applicaiton项目的build.gradle
中增加apply plugin: "jp.leafytree.android-scala"
,在dependencies 中添加scala库和spray-json库
apply plugin: 'com.android.application'
apply plugin: "jp.leafytree.android-scala"
dependencies {
...
compile 'org.scala-lang:scala-library:2.11.8'
compile 'io.spray:spray-json_2.11:1.3.3'
...
}
scala-library:2.11.8
表示用的是scala的2.11.8版本,而io.spray:spray-json_2.11:1.3.3
中的2.11
表示spray-json兼容scala的2.11.x
版本,scala的一大坑人之处就是不同版本之间兼容做的不太好,总是报许多莫名其妙的错误,因此在选用scala的第三库的时候要特别留心它所兼容的scala版本号。
上面的环境搭建好了以后,照着spray-json的说明文档编译的时候还是出了不少的错,后来鬼使神差地修改了一下scala编译器的配置选项,竟然OK了,可能是因为我电脑上只能装的jdk是1.8的缘故。
另外我电脑上也安装了Scala的开发环境,不知道不安装对编译程序有没有影响,我电脑上安装的scala版本是2.12.2,至于如何安装scala,最好还是参考scala的官网
解析数据
现以豆瓣网上电影Top250数据为例子,相关Api参见此处,因为限于篇幅,只是列出了前两部电影,其格式如下:
{
"count": 20,
"start": 0,
"total": 250,
"title": "豆瓣电影Top250",
"subjects": [
{
"rating": {
"max": 10,
"average": 9.6,
"stars": "50",
"min": 0
},
"genres": [
"犯罪",
"剧情"
],
"title": "肖申克的救赎",
"casts": [
{
"alt": "https://movie.douban.com/celebrity/1054521/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/17525.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/17525.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/17525.jpg"
},
"name": "蒂姆·罗宾斯",
"id": "1054521"
},
{
"alt": "https://movie.douban.com/celebrity/1054534/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/34642.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/34642.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/34642.jpg"
},
"name": "摩根·弗里曼",
"id": "1054534"
},
{
"alt": "https://movie.douban.com/celebrity/1041179/",
"avatars": {
"small": "https://img1.doubanio.com/img/celebrity/small/5837.jpg",
"large": "https://img1.doubanio.com/img/celebrity/large/5837.jpg",
"medium": "https://img1.doubanio.com/img/celebrity/medium/5837.jpg"
},
"name": "鲍勃·冈顿",
"id": "1041179"
}
],
"collect_count": 1135009,
"original_title": "The Shawshank Redemption",
"subtype": "movie",
"directors": [
{
"alt": "https://movie.douban.com/celebrity/1047973/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/230.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/230.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/230.jpg"
},
"name": "弗兰克·德拉邦特",
"id": "1047973"
}
],
"year": "1994",
"images": {
"small": "https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p480747492.webp",
"large": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p480747492.webp",
"medium": "https://img3.doubanio.com/view/movie_poster_cover/spst/public/p480747492.webp"
},
"alt": "https://movie.douban.com/subject/1292052/",
"id": "1292052"
},
{
"rating": {
"max": 10,
"average": 9.5,
"stars": "50",
"min": 0
},
"genres": [
"剧情",
"爱情",
"同性"
],
"title": "霸王别姬",
"casts": [
{
"alt": "https://movie.douban.com/celebrity/1003494/",
"avatars": {
"small": "https://img1.doubanio.com/img/celebrity/small/67.jpg",
"large": "https://img1.doubanio.com/img/celebrity/large/67.jpg",
"medium": "https://img1.doubanio.com/img/celebrity/medium/67.jpg"
},
"name": "张国荣",
"id": "1003494"
},
{
"alt": "https://movie.douban.com/celebrity/1050265/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/46345.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/46345.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/46345.jpg"
},
"name": "张丰毅",
"id": "1050265"
},
{
"alt": "https://movie.douban.com/celebrity/1035641/",
"avatars": {
"small": "https://img1.doubanio.com/img/celebrity/small/1399268395.47.jpg",
"large": "https://img1.doubanio.com/img/celebrity/large/1399268395.47.jpg",
"medium": "https://img1.doubanio.com/img/celebrity/medium/1399268395.47.jpg"
},
"name": "巩俐",
"id": "1035641"
}
],
"collect_count": 810842,
"original_title": "霸王别姬",
"subtype": "movie",
"directors": [
{
"alt": "https://movie.douban.com/celebrity/1023040/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/750.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/750.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/750.jpg"
},
"name": "陈凯歌",
"id": "1023040"
}
],
"year": "1993",
"images": {
"small": "https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p1910813120.webp",
"large": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p1910813120.webp",
"medium": "https://img3.doubanio.com/view/movie_poster_cover/spst/public/p1910813120.webp"
},
"alt": "https://movie.douban.com/subject/1291546/",
"id": "1291546"
}
]
}
根据上面的json定义对应的实体类,一般scala
用case class
,类似于java中
的JavaBean
、kotlin
中的data class
/**
* 评分
*/
case class Rating(max: Int, average: Float, stars: String, min: Int)
/**
* 图片
*/
case class Avatars(small: String, large: String, medium: String)
/**
* 人(演员或者导演)
*/
case class Person(alt: String, avatars: Avatars, name: String, id: String)
/**
* 电影主题
*/
case class Subject(
rating: Rating,
genres: List[String],
title: String,
casts: List[Person],
collect_count: Int,
original_title: String,
subtype: String,
directors: List[Person],
year: String,
images: Avatars,
alt: String,
id: String
)
/**
* Top250,整体返回的json
**/
case class Top250(count: Int, start: Int, total: Int, subjects: List[Subject], title: String)
定义解析协议
object ResultJsonProtocol extends DefaultJsonProtocol {
implicit val ratingFormat = jsonFormat(Rating, "max", "average", "stars", "min")
implicit val avatarsFormat = jsonFormat(Avatars, "small", "large", "medium")
implicit val personFormat = jsonFormat(Person, "alt", "avatars", "name", "id")
implicit val subjectFormat = jsonFormat(Subject, "rating", "genres", "title", "casts", "collect_count", "original_title", "subtype", "directors", "year", "images", "alt", "id")
implicit val resultFormat = jsonFormat(Top250, "count", "start", "total", "subjects", "title")
}
使用解析协议解析数据
import spray.json._
val jsonValue =
"""
|{
| "count": 20,
| "start": 0,
| "total": 250,
| "title": "豆瓣电影Top250",
| "subjects": [
| {
| "rating": {
| "max": 10,
| "average": 9.6,
| "stars": "50",
| "min": 0
| },
| "genres": [
| "犯罪",
| "剧情"
| ],
| "title": "肖申克的救赎",
| "casts": [
| {
| "alt": "https://movie.douban.com/celebrity/1054521/",
| "avatars": {
| "small": "https://img3.doubanio.com/img/celebrity/small/17525.jpg",
| "large": "https://img3.doubanio.com/img/celebrity/large/17525.jpg",
| "medium": "https://img3.doubanio.com/img/celebrity/medium/17525.jpg"
| },
| "name": "蒂姆·罗宾斯",
| "id": "1054521"
| },
| {
| "alt": "https://movie.douban.com/celebrity/1054534/",
| "avatars": {
| "small": "https://img3.doubanio.com/img/celebrity/small/34642.jpg",
| "large": "https://img3.doubanio.com/img/celebrity/large/34642.jpg",
| "medium": "https://img3.doubanio.com/img/celebrity/medium/34642.jpg"
| },
| "name": "摩根·弗里曼",
| "id": "1054534"
| },
| {
| "alt": "https://movie.douban.com/celebrity/1041179/",
| "avatars": {
| "small": "https://img1.doubanio.com/img/celebrity/small/5837.jpg",
| "large": "https://img1.doubanio.com/img/celebrity/large/5837.jpg",
| "medium": "https://img1.doubanio.com/img/celebrity/medium/5837.jpg"
| },
| "name": "鲍勃·冈顿",
| "id": "1041179"
| }
| ],
| "collect_count": 1135009,
| "original_title": "The Shawshank Redemption",
| "subtype": "movie",
| "directors": [
| {
| "alt": "https://movie.douban.com/celebrity/1047973/",
| "avatars": {
| "small": "https://img3.doubanio.com/img/celebrity/small/230.jpg",
| "large": "https://img3.doubanio.com/img/celebrity/large/230.jpg",
| "medium": "https://img3.doubanio.com/img/celebrity/medium/230.jpg"
| },
| "name": "弗兰克·德拉邦特",
| "id": "1047973"
| }
| ],
| "year": "1994",
| "images": {
| "small": "https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p480747492.webp",
| "large": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p480747492.webp",
| "medium": "https://img3.doubanio.com/view/movie_poster_cover/spst/public/p480747492.webp"
| },
| "alt": "https://movie.douban.com/subject/1292052/",
| "id": "1292052"
| },
| {
| "rating": {
| "max": 10,
| "average": 9.5,
| "stars": "50",
| "min": 0
| },
| "genres": [
| "剧情",
| "爱情",
| "同性"
| ],
| "title": "霸王别姬",
| "casts": [
| {
| "alt": "https://movie.douban.com/celebrity/1003494/",
| "avatars": {
| "small": "https://img1.doubanio.com/img/celebrity/small/67.jpg",
| "large": "https://img1.doubanio.com/img/celebrity/large/67.jpg",
| "medium": "https://img1.doubanio.com/img/celebrity/medium/67.jpg"
| },
| "name": "张国荣",
| "id": "1003494"
| },
| {
| "alt": "https://movie.douban.com/celebrity/1050265/",
| "avatars": {
| "small": "https://img3.doubanio.com/img/celebrity/small/46345.jpg",
| "large": "https://img3.doubanio.com/img/celebrity/large/46345.jpg",
| "medium": "https://img3.doubanio.com/img/celebrity/medium/46345.jpg"
| },
| "name": "张丰毅",
| "id": "1050265"
| },
| {
| "alt": "https://movie.douban.com/celebrity/1035641/",
| "avatars": {
| "small": "https://img1.doubanio.com/img/celebrity/small/1399268395.47.jpg",
| "large": "https://img1.doubanio.com/img/celebrity/large/1399268395.47.jpg",
| "medium": "https://img1.doubanio.com/img/celebrity/medium/1399268395.47.jpg"
| },
| "name": "巩俐",
| "id": "1035641"
| }
| ],
| "collect_count": 810842,
| "original_title": "霸王别姬",
| "subtype": "movie",
| "directors": [
| {
| "alt": "https://movie.douban.com/celebrity/1023040/",
| "avatars": {
| "small": "https://img3.doubanio.com/img/celebrity/small/750.jpg",
| "large": "https://img3.doubanio.com/img/celebrity/large/750.jpg",
| "medium": "https://img3.doubanio.com/img/celebrity/medium/750.jpg"
| },
| "name": "陈凯歌",
| "id": "1023040"
| }
| ],
| "year": "1993",
| "images": {
| "small": "https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p1910813120.webp",
| "large": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p1910813120.webp",
| "medium": "https://img3.doubanio.com/view/movie_poster_cover/spst/public/p1910813120.webp"
| },
| "alt": "https://movie.douban.com/subject/1291546/",
| "id": "1291546"
| }
| ]
|}
""".stripMargin.parseJson //
import ResultJsonProtocol._
val top250 = jsonValue.convertTo[Top250]
println("count:" + top250.count + ";start" + top250.start + ";start:" + top250.total + ";title:" + top250.title)
top250.subjects.foreach(item => println(item.title))
完整示例参考我的github上正在开发的项目Scalandroid