복붙노트

[SCALA] 어떻게 표준 스칼라 클래스를 사용하여 스칼라에서 JSON을 구문 분석?

SCALA

어떻게 표준 스칼라 클래스를 사용하여 스칼라에서 JSON을 구문 분석?

내가 JSON 코드를 구문 분석 스칼라 2.8 JSON 클래스의 빌드를 사용하고 있습니다. 나는 때문에 최소화 의존성에 Liftweb 하나 또는 기타를 사용하지 않습니다.

내가 그 일을하고 방법은 그것을 할 수있는 더 좋은 방법이 너무 절대적으로 보인다?

import scala.util.parsing.json._
...
val json:Option[Any] = JSON.parseFull(jsonString)
val map:Map[String,Any] = json.get.asInstanceOf[Map[String, Any]]
val languages:List[Any] = map.get("languages").get.asInstanceOf[List[Any]]
languages.foreach( langMap => {
val language:Map[String,Any] = langMap.asInstanceOf[Map[String,Any]]
val name:String = language.get("name").get.asInstanceOf[String]
val isActive:Boolean = language.get("is_active").get.asInstanceOf[Boolean]
val completeness:Double = language.get("completeness").get.asInstanceOf[Double]
}

해결법

  1. ==============================

    1.이 클래스 캐스트를 할 것입니다 추출기 기반으로하는 솔루션이다 :

    이 클래스 캐스트를 할 것입니다 추출기 기반으로하는 솔루션이다 :

    class CC[T] { def unapply(a:Any):Option[T] = Some(a.asInstanceOf[T]) }
    
    object M extends CC[Map[String, Any]]
    object L extends CC[List[Any]]
    object S extends CC[String]
    object D extends CC[Double]
    object B extends CC[Boolean]
    
    val jsonString =
        """
          {
            "languages": [{
                "name": "English",
                "is_active": true,
                "completeness": 2.5
            }, {
                "name": "Latin",
                "is_active": false,
                "completeness": 0.9
            }]
          }
        """.stripMargin
    
    val result = for {
        Some(M(map)) <- List(JSON.parseFull(jsonString))
        L(languages) = map("languages")
        M(language) <- languages
        S(name) = language("name")
        B(active) = language("is_active")
        D(completeness) = language("completeness")
    } yield {
        (name, active, completeness)
    }
    
    assert( result == List(("English",true,2.5), ("Latin",false,0.9)))
    

    이 말에 목록을 얻을 수 있도록 시작시 루프 나는 인위적으로 목록에 결과를 포장. for 루프의 나머지 I가 발전기가 사실 이용 (사용하여 <-) 값과 정의 적용된 방법을 활용한다 (= 사용).

    (이전 대답은 멀리 편집 - 당신이 궁금하면 편집 내역을 확인)

  2. ==============================

    2.이것은 내가 패턴 일치를 수행 방법입니다 :

    이것은 내가 패턴 일치를 수행 방법입니다 :

    val result = JSON.parseFull(jsonStr)
    result match {
      // Matches if jsonStr is valid JSON and represents a Map of Strings to Any
      case Some(map: Map[String, Any]) => println(map)
      case None => println("Parsing failed")
      case other => println("Unknown data structure: " + other)
    }
    
  3. ==============================

    3.나는 그것이 옳은 길을 날 실망했다, huynhjl의 대답 @ 좋아한다. 그러나, 오류 조건을 처리하기에 크지 않다. 원하는 노드가 존재하지 않는 경우, 당신은 캐스트 예외가. 더 나은이를 처리하는 옵션을 사용하도록 약간이 적응했습니다.

    나는 그것이 옳은 길을 날 실망했다, huynhjl의 대답 @ 좋아한다. 그러나, 오류 조건을 처리하기에 크지 않다. 원하는 노드가 존재하지 않는 경우, 당신은 캐스트 예외가. 더 나은이를 처리하는 옵션을 사용하도록 약간이 적응했습니다.

    class CC[T] {
      def unapply(a:Option[Any]):Option[T] = if (a.isEmpty) {
        None
      } else {
        Some(a.get.asInstanceOf[T])
      }
    }
    
    object M extends CC[Map[String, Any]]
    object L extends CC[List[Any]]
    object S extends CC[String]
    object D extends CC[Double]
    object B extends CC[Boolean]
    
    for {
      M(map) <- List(JSON.parseFull(jsonString))
      L(languages) = map.get("languages")
      language <- languages
      M(lang) = Some(language)
      S(name) = lang.get("name")
      B(active) = lang.get("is_active")
      D(completeness) = lang.get("completeness")
    } yield {
      (name, active, completeness)
    }
    

    물론,이 오류를 처리 너무 많은 그들을 피하기하지 않습니다. json으로 노드 중 하나가 누락 된 경우이 빈 목록을 얻을 것입니다. 당신은 행동하기 전에 노드의 존재를 확인하기 위해 일치를 사용할 수 있습니다 ...

    for {
      M(map) <- Some(JSON.parseFull(jsonString))
    } yield {
      map.get("languages") match {
        case L(languages) => {
          for {
            language <- languages
            M(lang) = Some(language)
            S(name) = lang.get("name")
            B(active) = lang.get("is_active")
            D(completeness) = lang.get("completeness")
          } yield {
            (name, active, completeness)
          }        
        }
        case None => "bad json"
      }
    }
    
  4. ==============================

    4.나는 캐스팅을 방지하는 방법으로 패턴 매칭을 선호, 몇 가지를 시도했지만 컬렉션 유형에 대한 유형의 삭제에 문제가 다 퉜다.

    나는 캐스팅을 방지하는 방법으로 패턴 매칭을 선호, 몇 가지를 시도했지만 컬렉션 유형에 대한 유형의 삭제에 문제가 다 퉜다.

    가장 큰 문제는 해석 결과의 완전한 유형이 JSON 데이터의 구조를 반영하고 완전히 상태로 복잡하거나 불가능 중 하나 인 것 같다. 나는 상관 유형 정의를 절단하는 데 사용되는 이유는 것 같다. 캐스팅의 필요성에 대한 단서를 사용.

    나는 간결하지만 문제의 코드에 의해 암시 JSON 데이터에 매우 특이하다 아래로 뭔가를 해킹했습니다. 뭔가 더 일반적인 더 만족스러운 것이 있지만, 매우 우아한 것이 있는지 확실하지 않습니다.

    implicit def any2string(a: Any)  = a.toString
    implicit def any2boolean(a: Any) = a.asInstanceOf[Boolean]
    implicit def any2double(a: Any)  = a.asInstanceOf[Double]
    
    case class Language(name: String, isActive: Boolean, completeness: Double)
    
    val languages = JSON.parseFull(jstr) match {
      case Some(x) => {
        val m = x.asInstanceOf[Map[String, List[Map[String, Any]]]]
    
        m("languages") map {l => Language(l("name"), l("isActive"), l("completeness"))}
      }
      case None => Nil
    }
    
    languages foreach {println}
    
  5. ==============================

    5.

    val jsonString =
      """
        |{
        | "languages": [{
        |     "name": "English",
        |     "is_active": true,
        |     "completeness": 2.5
        | }, {
        |     "name": "Latin",
        |     "is_active": false,
        |     "completeness": 0.9
        | }]
        |}
      """.stripMargin
    
    val result = JSON.parseFull(jsonString).map {
      case json: Map[String, List[Map[String, Any]]] =>
        json("languages").map(l => (l("name"), l("is_active"), l("completeness")))
    }.get
    
    println(result)
    
    assert( result == List(("English", true, 2.5), ("Latin", false, 0.9)) )
    
  6. ==============================

    6.당신은 다음과 같이 할 수있다! JSON 코드를 분석하는 것은 매우 쉽습니다 : P

    당신은 다음과 같이 할 수있다! JSON 코드를 분석하는 것은 매우 쉽습니다 : P

    package org.sqkb.service.common.bean
    
    import java.text.SimpleDateFormat
    
    import org.json4s
    import org.json4s.JValue
    import org.json4s.jackson.JsonMethods._
    //import org.sqkb.service.common.kit.{IsvCode}
    
    import scala.util.Try
    
    /**
      *
      */
    case class Order(log: String) {
    
      implicit lazy val formats = org.json4s.DefaultFormats
    
      lazy val json: json4s.JValue = parse(log)
    
      lazy val create_time: String = (json \ "create_time").extractOrElse("1970-01-01 00:00:00")
      lazy val site_id: String = (json \ "site_id").extractOrElse("")
      lazy val alipay_total_price: Double = (json \ "alipay_total_price").extractOpt[String].filter(_.nonEmpty).getOrElse("0").toDouble
      lazy val gmv: Double = alipay_total_price
      lazy val pub_share_pre_fee: Double = (json \ "pub_share_pre_fee").extractOpt[String].filter(_.nonEmpty).getOrElse("0").toDouble
      lazy val profit: Double = pub_share_pre_fee
    
      lazy val trade_id: String = (json \ "trade_id").extractOrElse("")
      lazy val unid: Long = Try((json \ "unid").extractOpt[String].filter(_.nonEmpty).get.toLong).getOrElse(0L)
      lazy val cate_id1: Int = (json \ "cate_id").extractOrElse(0)
      lazy val cate_id2: Int = (json \ "subcate_id").extractOrElse(0)
      lazy val cate_id3: Int = (json \ "cate_id3").extractOrElse(0)
      lazy val cate_id4: Int = (json \ "cate_id4").extractOrElse(0)
      lazy val coupon_id: Long = (json \ "coupon_id").extractOrElse(0)
    
      lazy val platform: Option[String] = Order.siteMap.get(site_id)
    
    
      def time_fmt(fmt: String = "yyyy-MM-dd HH:mm:ss"): String = {
        val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        val date = dateFormat.parse(this.create_time)
        new SimpleDateFormat(fmt).format(date)
      }
    
    }
    
  7. from https://stackoverflow.com/questions/4170949/how-to-parse-json-in-scala-using-standard-scala-classes by cc-by-sa and MIT license