Как преобразовать JSON в тип в Scala
Моя проблема: я получаю текст JSON, скажем, твиттер. Затем я хочу преобразовать этот текст в собственный объект в scala. Есть ли стандартный метод для этого? Я также использую Play 2
Вот что я
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
Я лично предпочитаю lift-json
, но это довольно легко сделать с помощью библиотеки Play JSON:
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)
Так что да, выглядит примерно так.
Ответ 2
Посмотрите Lift-Json. Он является частью веб-фрейма Lift, но может использоваться как автономная библиотека. Он может анализировать json в классах case (и их коллекции, например, списки и карты), и он не требует добавления аннотаций. Он также поддерживает классы рендеринга как 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)))
*/
Ответ 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
, он пытается найти геттеры/сеттеры, исследуя методы самостоятельно. Если бы это было так, все было бы проще, можно было бы написать просто
@scala.reflect.BeanInfo
case class Name {
var first: String;
var last: String;
}
Ответ 4
Попробуйте Jerkson lib: https://github.com/codahale/jerkson/
Это json-библиотека для scala на основе Jackson. Он включен для воспроизведения 2: http://www.playframework.org/documentation/2.0.2/ScalaJson
Пример:
case class Person(id: Long, name: String)
parse[Person]("""{"id":1,"name":"Coda"}""") //=> Person(1,"Coda")
Ответ 5
преобразовать в jsvalue, используя Json.parse(string), затем добавить оператор как [T], чтобы извлечь значение