2012-08-09 77 views
11

我的问题是我收到来自say,twitter的JSON文本。然后我想将这个文本转换为scala中的本地对象。有没有一个标准的方法来做到这一点?我还使用播放2如何将JSON转换为Scala中的类型

这里是我有什么

import scala.io.Source.{fromInputStream} 
import java.net._ 

val url = new URL("https://api.twitter.com/1/trends/1.json") 
val content = fromInputStream(url.openStream).getLines.mkString("\n") 
val json = Json.parse(content) 
val a = (json \ "trends") 
Ok(a(0)) 

我想从JSON

+1

的[I如何构建和解析Scala中/郊游JSON字符串]可能重复(http://stackoverflow.com/questions/927983/how-can-i-construct-and-parse-a-json-string-in-scala-lift) – 2012-08-09 19:42:19

+0

还有Jerkson和其他一些不太知名的图书馆 – 2012-08-09 19:48:03

+1

@ om-nom-nom:我不认为这是算作重复 - 另一个问题具体是关于电梯,而不是戏剧(无论如何都是相当古老的)。 – 2012-08-09 20:22:59

回答

4

我个人更喜欢lift-json,但它很容易与Play's JSON library做到这一点:

import play.api.libs.json._ 
import scala.io.Source 

case class Trend(name: String, url: String) 

implicit object TrendReads extends Reads[Trend] { 
    def reads(json: JsValue) = Trend(
    (json \ "name").as[String], 
    (json \ "url").as[String] 
) 
} 

val url = new java.net.URL("https://api.twitter.com/1/trends/1.json") 
val content = Source.fromInputStream(url.openStream).getLines.mkString("\n") 
val trends = Json.parse(content) match { 
    case JsArray(Seq(t)) => Some((t \ "trends").as[Seq[Trend]]) 
    case _ => None 
} 

眼下这将产生如下:

scala> trends.foreach(_.foreach(println)) 
Trend(#TrueFactsAboutMe,http://twitter.com/search/?q=%23TrueFactsAboutMe) 
Trend(#200mFinal,http://twitter.com/search/?q=%23200mFinal) 
Trend(Jamaica 1,2,3,http://twitter.com/search/?q=%22Jamaica%201,2,3%22) 
Trend(#DontComeToMyHouse,http://twitter.com/search/?q=%23DontComeToMyHouse) 
Trend(Lauren Cheney,http://twitter.com/search/?q=%22Lauren%20Cheney%22) 
Trend(Silver & Bronze,http://twitter.com/search/?q=%22Silver%20&%20Bronze%22) 
Trend(Jammer Martina,http://twitter.com/search/?q=%22Jammer%20Martina%22) 
Trend(Japan 2-0,http://twitter.com/search/?q=%22Japan%202-0%22) 
Trend(Prata e Bronze,http://twitter.com/search/?q=%22Prata%20e%20Bronze%22) 
Trend(Final 200m,http://twitter.com/search/?q=%22Final%20200m%22) 

所以是的,看起来是正确的。

3

我建议使用Jackson JSON processor得到所有的趋势名。它适用于Java和Scala。您只需将注释添加到您的类中,即可描述如何将JSON数据映射到本机对象。

一个例子:

import scala.reflect.BeanProperty 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.annotate._ 

class User { 
    @BeanProperty var gender: String = null 
    @BeanProperty var verified: Boolean = false 
    @BeanProperty var userImage: Array[Byte] = null 
    @BeanProperty var name: Name = null 
} 

case class Name { 
    @BeanProperty var first: String = null; 
    @BeanProperty var last: String = null; 
} 

object Json { 
    def main(argv: Array[String]) { 
    val input = """{ 
    "name" : { "first" : "Joe", "last" : "Sixpack" }, 
    "verified" : false, 
    "userImage" : "Rm9vYmFyIQ==" 
}"""; 

    val mapper = new ObjectMapper(); // can reuse, share globally 
    val user: User = mapper.readValue(input, classOf[User]); 

    print(user.name.first); 
    } 
} 

该解决方案,你必须标注每场@BeanProperty轻微的麻烦,但我不知道一个简单的方法。


备注:据我所知,杰克逊并没有使用javax.bean.Introspector,它试图通过自行检查方法来寻找getter/setter方法。如果有,事情就会变得更容易,将有可能写只是

@scala.reflect.BeanInfo 
case class Name { 
    var first: String; 
    var last: String; 
} 
3

看一看Lift-Json。它是Lift web框架的一部分,但可以用作独立库。它可以将json解析为案例类(以及这些类的集合,例如列表和地图),并且不需要添加注释。它还支持渲染类为json,并合并和查询json。

下面是从他们的网站采取了一个例子:

import net.liftweb.json._ 
implicit val formats = DefaultFormats // Brings in default date formats etc. 

case class Child(name: String, age: Int, 
       birthdate: Option[java.util.Date]) 
case class Address(street: String, city: String) 
case class Person(name: String, address: Address, 
       children: List[Child]) 
val json = parse(""" 
     { "name": "joe", 
      "address": { 
      "street": "Bulevard", 
      "city": "Helsinki" 
      }, 
      "children": [ 
      { 
       "name": "Mary", 
       "age": 5 
       "birthdate": "2004-09-04T18:06:22Z" 
      }, 
      { 
       "name": "Mazy", 
       "age": 3 
      } 
      ] 
     } 
     """) 

json.extract[Person] 
/* Person = Person(joe, Address(Bulevard,Helsinki), 
        List(Child(Mary,5,Some(Sat Sep 04 18:06:22 EEST 2004)), 
         Child(Mazy,3,None))) 
*/ 
相关问题