2012-08-09 16 views
11

Mi problema es que recibo un texto JSON de say, twitter. Luego quiero convertir este texto a un objeto nativo en scala. ¿Hay un método estándar para hacer esto? También estoy usando Play 2Cómo convertir JSON a un tipo en Scala

Aquí es lo que tengo

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

quiero conseguir todo el nombre de las tendencias de la JSON

+1

posible duplicado de [¿Cómo construir I y analizar una cadena JSON en Scala/Lift] (http://stackoverflow.com/questions/927983/how-can-i-construct-and-parse-a-json-string-in-scala-lift) –

+0

también hay Jerkson y algunas otras bibliotecas menos conocidas –

+1

@ om-nom-nom: No creo que esto cuenta como un duplicado; la otra pregunta es específicamente sobre Levantar, no Jugar (y es bastante antigua, de todos modos). –

Respuesta

4

yo personalmente prefiero lift-json, pero es bastante fácil de hacer esto con 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 
} 

En este momento esto produce lo siguiente:

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) 

Así que sí, se ve bien.

3

Es mejor utilizar Jackson JSON processor. Funciona tanto para Java como para Scala. Simplemente agrega anotaciones a sus clases que describen cómo desea mapear datos JSON a sus objetos nativos.

Un ejemplo:

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

Esta solución tiene una ligera molestia que hay que anotar todos los campos con @BeanProperty, pero no sé una manera más sencilla.


Observación: En la medida que yo sepa, Jackson no utiliza javax.bean.Introspector, se trata de encontrar getters/setters mediante el examen de los métodos por sí mismo. Si así fuera, las cosas habrían sido más fácil, sería posible escribir simplemente

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

Tener un vistazo a Lift-Json. Es parte del marco web de Lift, pero se puede usar como una biblioteca independiente. Puede analizar json en clases de casos (y colecciones de esos, por ejemplo, listas y mapas), y no requiere que agregue anotaciones. También admite clases de representación como json, y fusión y consulta de json.

Aquí es un ejemplo tomado de su página web:

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