Scala中解析json工具对比

写再前面的总结:

1, 做少量文件解析,优先用json4s,因为json4s时基于Scala开发的,对scala使用场景支持更好
2. 做大量数据的解析,追求序列化、反序列化速度时,考虑用fastjson,但是fastjson是基于java开发的,对scala支持不好。所以,除非遇到性能提升场景或者只是简单的json处理,才考虑在scala中用fastjson。

可选工具:
fastjson
gson
json4s(jackson的scala版本)
lift-json
spray-json
circle
play-json

一、fastjson 简介

一、阿里巴巴FastJson是一个Json处理工具包,包括“序列化”和“反序列化”两部分,它具备如下特征:
速度最快,测试表明,fastjson具有极快的性能,超越任其他的Java Json parser。包括自称最快的JackJson;
功能强大,完全支持Java Bean、集合、Map、日期、Enum,支持范型,支持自省;无依赖;

Json解析工具使用的 json-smart,曾经对比过Java的fastjson、gson。Scala的json4s、lift-json。其中 json-smart 解析速度是最快的。

在这里插入图片描述

二、fastjson 使用对比 json4s

json4s官网样例:https://github.com/json4s/json4s

import org.scalatest.funsuite

import org.json4s.jackson.JsonMethods._
import org.json4s._
import org.json4s.JsonDSL._

import scala.collection.{immutable, mutable}
import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONWriter
import com.alibaba.fastjson2.JSONReader



class BasicTest extends funsuite.AnyFunSuite {

  test("option map 使用") {
    val m1 = Map("a" -> 1, "b" -> 2)
    val c1 = m1.get("c") //返回Option
    val m2 = Some(Map("a" -> 1, "b" -> 2))
    val a = m2.get("a") //返回value,key不存在会报错
    // val c2=m2.get("c") //返回value,key不存在会报错
    val m3 = m2.get //get 不带参数,是取option里面的值
    println(m3)

    val str: Option[String] = Some("test")
    str match {
      case Some(x) => x
      case None => "NA"
    }
    str.getOrElse("NA")
  }


  test("json4s 官网示例1"){
    case class Winner(id: Long, numbers: List[Int])
    case class Lotto(id: Long, winningNumbers: List[Int], winners: List[Winner], drawDate: Option[java.util.Date])

    val winners = List(Winner(23, List(2, 45, 34, 23, 3, 5)), Winner(54, List(52, 3, 12, 11, 18, 22)))
    val lotto = Lotto(5, List(2, 45, 34, 23, 7, 5, 3), winners, None)

    val json =
      ("lotto" ->
        ("lotto-id" -> lotto.id) ~
          ("winning-numbers" -> lotto.winningNumbers) ~
          ("draw-date" -> lotto.drawDate.map(_.toString)) ~
          ("winners" ->
            lotto.winners.map { w =>
              (("winner-id" -> w.id) ~
                ("numbers" -> w.numbers))}))

    println(compact(render(json)))
  }

  test("json4s官网示例2"){
    val lotto1 = parse("""{
         "lotto":{
           "lotto-id":5,
           "winning-numbers":[2,45,34,23,7,5,3],
           "winners":[{
             "winner-id":23,
             "numbers":[2,45,34,23,3,5]
           }]
         }
       }""")
    val lotto2 = parse("""{
         "lotto":{
           "winners":[{
             "winner-id":54,
             "numbers":[52,3,12,11,18,22]
           }]
         }
       }""")
    val mergedLotto = lotto1 merge lotto2
    println(pretty(render(mergedLotto)))
    val Diff(changed, added, deleted) = mergedLotto diff lotto1
    println(changed, added, deleted)
  }
  //不能在方法中定义case class
  case class Child(name: String, age: Int, birthdate: Option[java.util.Date])
  case class Address(street: String, city: String)//提取的字段名要和json中的field一致
  case class Address2(street: String, city: String,home:Option[String])//可选字段用Option,否则没有的话会报错
  case class Person(name: String, address: Address, children: List[Child])
  test("json4s 官网示例3"){

    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
             }
           ]
         }
       """)
    implicit val formats: Formats = DefaultFormats
    println(json.extract[Person])
    val addressJson = json  \ "address"
    println(addressJson.extract[Address])
    println(addressJson.extract[Address2])
    println( (json \ "children").extract[List[Child]])

  }
  test("fastjson对应示例3"){

    val jsonStr = """
         { "name": "joe",
           "address": {
             "street": "Bulevard",
             "city": "Helsinki"
           },
           "children": [
             {
               "name": "Mary",
               "age": 5,
               "birthdate": "2004-09-04T18:06:22Z"
             },
             {
               "name": "Mazy",
               "age": 3
             }
           ]
         }
       """

    println(JSON.parseObject(jsonStr,classOf[Person])) //报错
  }
 

  test("fastjson") {
    val jobJsonStr = """{"name":"Job","age":19,"tasks":[{"name":"a"},{"name":"b"}],"js":{"a2":1,"b2":2}}"""
    val fJson = JSON.parseObject(jobJsonStr)
    println("\n****fastjson****")
    println(fJson.get("name"))
    val m2=Map("a"->"1","b"->"2")

    import collection.JavaConverters._
    println(JSON.toJSONString(m2.asJava, Array[JSONWriter.Feature](): _*))

    //println(JSON.parseObject("""{"name":"Job","age":"19"}""",classOf[model]))

    println(JSON.parseObject("""{"name":"Job","age":19}""",classOf[java.util.Map[String, String]]).asScala)

    //println(JSON.parseObject(jobJsonStr).getObject("js",classOf[java.util.Map[String, String]],Array[JSONReader.Feature](): _*).asScala.mkString(","))//a 会报冲突

    // val m=JSON.parseObject("""{"name":"Job","age":"19"}""",classOf[Map[String, String]],JSONReader.Feature.FieldBased)//实现不了。。。类似json4j的那种便捷的变换


    val tmpStr=JSON.parseObject(jobJsonStr).getJSONObject("js").toString
    println(tmpStr)
    println(JSON.parseObject(tmpStr,classOf[java.util.Map[String, String]]).asScala.mkString(","))//a如果报冲突,按理也应该报冲突parseObject(String text, Class<T> clazz) 和 parseObject(String text, Type type)


  }



}



要想像json4s那样再scala中用好fastjson是比较难的,因为jastjson都要基于java类做转化,会有不少适配问题:例如

关于json4s extract的隐式参数:

def extract[A](implicit formats : org.json4s.Formats, mf : scala.reflect.Manifest[A]) : A = { /* compiled code */ }
//formats来源
implicit val formats: Formats = DefaultFormats
//mf来源,scala在运行时会隐式引入如下方法(待验证该描述)
scala.reflect.ManifestFactory.classType
//验证:Json4sTest.scala
object Json4sTest {
  def testMf[A](a:A)(implicit mf:scala.reflect.Manifest[A]):A={
    println(a.toString)
    a
  }

  def main(args: Array[String]): Unit = {
    testMf("abc")
  }
}

执行 
scalac -Xprint:typer Json4sTest.scala
输出:
Json4sTest.this.testMf[String]("abc")(scala.reflect.ManifestFactory.classType[String](classOf[java.lang.String]));

一定要用fastjson,并且子弟定义解析case class,就没有办法了吗?

有的,使用BeanProperty注解:



import com.alibaba.fastjson.JSON

import scala.beans.BeanProperty

object Class_ttt {
  
  class Person{
    
    var name:String = "zahngsan"
    var age :Int = 20
  }
  
  class Student(@BeanProperty val name:String,@BeanProperty val age:Int)
  
  
  /**
   * 封装:属性私有,提供共有的set/get方法
   *
   * scala中提供了一个注解@BeanProperty 能够自动生成java的get/set方法
   *
   * scala中可以使用java的API,java的很多API都要求有get/set方法,scala为了兼容java提供了@BeanProperty
   *
   *   @BeanProperty注解不能用于private修饰的属性上
   *
   *
   */
  def main(args: Array[String]): Unit = {
    
    val json ="""{"name":"lisi","age":"30"}"""
    val student: Student = JSON.parseObject(json,classOf[Student])
    println(student.name)
    
    val student2 = new Student("wangwu",23)
    println(JSON.toJSON(student2))
    
  }
  
}


其他参考:

json4s官方教程:https://github.com/json4s/json4s
json4s使用教程:https://www.cnblogs.com/yyy-blog/p/11819302.html
fastjson官方使用指导:https://github.com/alibaba/fastjson/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
fastjson2:https://github.com/alibaba/fastjson2
fastjson 升级 fastjson2:https://github.com/alibaba/fastjson2/wiki/fastjson_1_upgrade_cn
fastjson元素遍历:https://blog.csdn.net/Lzx116/article/details/126974187?ops_request_misc=&request_id=&biz_id=102&utm_term=scala%20fastjson%20getobject&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-126974187.142^v73^pc_search_v2,201^v4^add_ask,239^v2^insert_chatgpt&spm=1018.2226.3001.4187
scala和java的type于class:https://stackoverflow.com/questions/1135248/scala-equivalent-of-java-java-lang-classt-object
Scala中使用JSON.toJSONString报错:ambiguous reference to overloaded definition:https://developer.aliyun.com/article/627434
Scala中使用JSON.toJSONString报错 2:https://stackoverflow.com/questions/6209120/scala-ambiguous-reference-to-overloaded-definition-with-varargs
参考:
https://blog.csdn.net/weixin_44259720/article/details/115111105
https://juejin.cn/post/7090371049442803748
https://www.rokub.com/58902.html
https://blog.csdn.net/chongshan6464/article/details/100866144
https://blog.csdn.net/lvtula/article/details/93387861
https://www.jianshu.com/p/93ffc45c8010
fastjson测试:https://github.com/alibaba/fastjson2/wiki/fastjson_benchmark
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值