2012-08-09 40 views
11

Vấn đề của tôi là tôi nhận được một văn bản JSON từ nói, twitter. Sau đó, tôi muốn chuyển đổi văn bản này thành một đối tượng gốc trong scala. Có một phương pháp tiêu chuẩn để làm điều này? Tôi cũng đang sử dụng Chơi 2Làm thế nào để chuyển đổi JSON thành một loại trong Scala

Dưới đây là những gì tôi có

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)) 

Tôi muốn để có được tất cả các tên xu hướng từ JSON

+1

thể trùng lặp của [Làm thế nào tôi có thể xây dựng và phân tích một chuỗi JSON trong Scala/Lift] (http://stackoverflow.com/questions/927983/Làm thế nào-có thể-i-xây dựng-và-parse-a-json-string-in-scala-lift) –

+0

đó cũng là Jerkson và một số người khác ít được biết đến thư viện –

+1

@ om-nom-nom: Tôi không nghĩ rằng điều này được tính là một bản sao — câu hỏi khác là đặc biệt về Nâng, chứ không phải Play (và khá cổ xưa, dù sao). –

Trả lời

4

Cá nhân tôi thích lift-json, nhưng nó khá dễ dàng để làm điều này với 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 
} 

Ngay bây giờ này tạo ra như sau:

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) 

Vì vậy, vâng, có vẻ đúng.

3

tôi đề nghị sử dụng Jackson JSON processor. Nó hoạt động cả cho Java và Scala. Bạn chỉ cần thêm chú thích vào các lớp của bạn, trong đó mô tả cách bạn muốn ánh xạ dữ liệu JSON tới các đối tượng gốc của bạn.

Một ví dụ:

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); 
    } 
} 

Giải pháp này có một rắc rối nhỏ mà bạn phải chú thích mọi lĩnh vực với @BeanProperty, nhưng tôi không biết một cách đơn giản hơn.


Ghi chú: Theo như tôi biết, Jackson không sử dụng javax.bean.Introspector, nó cố gắng để tìm getters/setters bằng cách kiểm tra các phương pháp của chính nó. Nếu có, mọi thứ sẽ dễ dàng hơn, bạn chỉ có thể viết

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

Hãy xem Lift-Json. Nó là một phần của khung công tác Nâng cao, nhưng có thể được sử dụng như một thư viện độc lập. Nó có thể phân tích cú pháp json thành các lớp trường hợp (và các bộ sưu tập của các trường hợp đó, ví dụ: danh sách và bản đồ) và không yêu cầu bạn thêm chú thích. Nó cũng hỗ trợ các lớp dựng hình là json, và hợp nhất và truy vấn json.

Dưới đây là một ví dụ lấy từ trang web của họ:

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))) 
*/ 
Các vấn đề liên quan