如何将 JSON 转换为 Scala 中的类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11889907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:29:24  来源:igfitidea点击:

How to convert JSON to a type in Scala

jsonscalaplayframework

提问by Athiwat Chunlakhan

My problem is I receive an JSON text from say, twitter. Then I want to convert this text to an native object in scala. Is there a standard method to do this? I'm also using Play 2

我的问题是我收到了来自 twitter 的 JSON 文本。然后我想将此文本转换为 Scala 中的本机对象。有没有标准方法可以做到这一点?我也在用 Play 2

Here is what I have

这是我所拥有的

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

I want to get all the trends name from the JSON

我想从 JSON 中获取所有趋势名称

采纳答案by Travis Brown

I personally prefer lift-json, but it's pretty easy to do this with Play's JSON library:

我个人更喜欢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
}

Right now this produces the following:

现在这会产生以下结果:

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)

So yeah, looks about right.

所以是的,看起来差不多。

回答by Malte Schwerhoff

Have a look at Lift-Json. It is part of the Lift web framework, but can be used as a stand-alone library. It can parse json into case classes (and collections of those, e.g., lists and maps), and it does not require you to add annotations. It also supports rendering classes as json, and merging and querying of json.

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

Here is an example taken from their website:

这是从他们的网站上获取的示例:

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

回答by user1411778

Try Jerkson lib: https://github.com/codahale/jerkson/

试试 Jerkson 库:https: //github.com/codahale/jerkson/

It is a json library for scala based on Hymanson. It is included to play 2: http://www.playframework.org/documentation/2.0.2/ScalaJson

它是一个基于Hymanson 的scala json 库。包括播放 2:http: //www.playframework.org/documentation/2.0.2/ScalaJson

Example:

例子:

    case class Person(id: Long, name: String)
    parse[Person]("""{"id":1,"name":"Coda"}""") //=> Person(1,"Coda")

回答by Petr Pudlák

I suggest to use Hymanson JSON processor. It works both for Java and Scala. You just add annotations to your classes which describe how you want to map JSON data to your native objects.

我建议使用Hymanson JSON 处理器。它适用于 Java 和 Scala。您只需向您的类添加注释,这些注释描述您希望如何将 JSON 数据映射到您的本机对象。

An example:

一个例子:

import scala.reflect.BeanProperty
import org.codehaus.Hymanson.map.ObjectMapper;
import org.codehaus.Hymanson.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);
  }
}

This solution has a slight hassle that you have to annotate every field with @BeanProperty, but I don't know a simpler way.

这个解决方案有点麻烦,你必须用 注释每个字段@BeanProperty,但我不知道更简单的方法。



Remark: As far as I know, Hymanson doesn't use javax.bean.Introspector, it tries to find getters/setters by examining the methods by itself. If it did, things would have been easier, it would be possible to write just

备注:据我所知,Hymanson 不使用javax.bean.Introspector,它试图通过自己检查方法来查找 getter/setter。如果这样做,事情会更容易,可以只写

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

回答by Abdelwahed Houbouby

convert to jsvalue by using Json.parse(string) then add operator as[T] to extract the value

使用 Json.parse(string) 转换为 jsvalue 然后添加操作符 as[T] 来提取值