Scala'da hangi JSON kitaplığı kullanılmalı? [kapalı]


125

Bunun gibi bir JSON dizisi oluşturmam gerekiyor:

[
  { 'id': 1, 'name': 'John'},
  { 'id': 2, 'name': 'Dani'}
]

val jArray = JsArray();
jArray += (("id", "1"), ("name", "John"))
jArray += (("id", "2"), ("name", "Dani"))
println(jArray.dump)

jArrayGibi bir şeye satır ekleyebilmem gerekiyorjArray += ...

Buna en yakın kütüphane / çözüm nedir?


Yanıtlar:


219

Ne yazık ki bir JSON kitaplığı yazmak, Scala topluluğunun yapılacaklar listesi uygulamasını kodlamanın sürümüdür.

Oldukça çeşitli alternatifler var. Bunları belirli bir sırayla listelemiyorum, notlarla:

  1. parsing.json.JSON - Uyarı Bu kitaplık yalnızca Scala sürüm 2.9.x'e kadar kullanılabilir (yeni sürümlerde kaldırılmıştır)
  2. spray-json - Spray projesinden alınmıştır
  3. Jerkson ± - Uyarı şimdi Abandonware güzel (Java Jackson üzerine inşa) kütüphane ama. Bunu kullanacaksanız, muhtemelen Scalding projesinin örneğini izleyin ve backchat.io çatalını kullanın.
  4. sjson - Debasish Ghosh tarafından
  5. lift-json - Lift projesinden ayrı olarak kullanılabilir
  6. json4s 💣 § ± - Diğer JSON kitaplıklarının kullanabileceği standart bir JSON AST oluşturmaya çalışan lift- json'dan bir ayıklama. Jackson destekli bir uygulama içerir
  7. Argonaut 💣 § - Scalaz'ın arkasındaki kişilerden, Scala için FP odaklı bir JSON kitaplığı
  8. play-json ± - Artık bağımsız olarak kullanılabilir, ayrıntılar için bu yanıta bakın
  9. dijon - Kullanışlı, güvenli ve verimli bir JSON kitaplığı, başlık altında jsoniter-scala kullanır .
  10. sonofjson - süper basit bir API hedefleyen JSON kitaplığı
  11. Jawn - Erik Osheim'ın Jackson veya daha hızlı hızını hedefleyen JSON kitaplığı
  12. Rapture JSON ± - 2, 4, 5, 6, 7, 11 veya Jackson'ı arka uç olarak kullanabilen bir JSON ön ucu
  13. circe 💣 - Argonaut çatal üzerine inşa kedilerin yerine scalaz arasında
  14. jsoniter-scala - ultra hızlı JSON codec bileşenlerinin derleme zamanında oluşturulması için Scala makroları
  15. jackson-module-scala - Scala'ya özgü veri türlerini desteklemek için Jackson için eklenti modülü
  16. borer - Scala'da verimli CBOR ve JSON (de) serileştirme

💣 = güvenlik açıklarını düzeltmedi, § = Scalaz entegrasyonuna sahip, ± = Jackson ile birlikte çalışmayı destekliyor JsonNode

In Snowplow biz Jackson arka uç ile json4s kullanın; Argonaut ile de güzel deneyimlerimiz oldu.


8
Lift-json'un daha büyük LIft projesine dahil olduğu doğru değil, sadece lift-json'a güvenebilirsiniz ve Lift projesinden başka hiçbir şey projenize gelmez.
fmpwizard

3
@AlexDean: parsing.json.JSON'un nesi bu kadar kötü?
Matthias Braun

Görünüşe göre play-json Play 2.2 ile piyasaya sürülecek ve şimdiden kullanabilirsiniz: mandubian.com/2013/02/21/play-json-stand-alone
Christiaan

2
@BjornTipling - iyi nokta, 2.11'de kullanımdan kaldırıldığına dair herhangi bir söz bulamıyorum. Bu yorum kaldırıldı
Alex Dean

2
Liste , performans, basitlik, bakım ve destek açısından açık ara en iyisine sahip olan jackson-module-scala'yı en üste koymalıdır .
lyomi

17

Lift-json 2.6 sürümünde ve gerçekten iyi çalışıyor (ve aynı zamanda çok iyi destekleniyor, bakımcı her zaman kullanıcıların bulabileceği hataları düzeltmeye hazır. Bunu kullanarak örnekleri github deposunda bulabilirsiniz.

Sorumluya (Joni Freeman) her zaman Lift posta listesinden ulaşılabilir . Posta listesinde çok yardımcı olan başka kullanıcılar da var.

@Alexey'in de belirttiği gibi, kütüphaneyi başka bir Scala sürümüyle kullanmak istiyorsanız, söyleyin 2.11.x, değiştirin scalaVersionve %%aşağıdaki gibi kullanın :

scalaVersion := "2.11.5" 

"net.liftweb" %% "lift-json" % "2.6"

Zaman geçtikçe en son sürümü öğrenmek için liftweb.net sitesini kontrol edebilirsiniz .


3
Ben de lift-json kullanıyorum ve harika bir kütüphane olduğuna kefil olabilirim. JSON'u hem ayrıştırmayı hem de üretmeyi / serileştirmeyi çok kolaylaştırır.
Dan Simon

1
"Net.liftweb"% "lift-json_2.10"% "2.5.1" için +1
Dylan Hogg

2
ve Scala 2.11 için: "net.liftweb"% "lift-json_2.11"% "2.6-M4"
Alexey

15

Jerkson kullanmanızı öneririm , çoğu temel tür dönüştürmeyi destekler:

scala> import com.codahale.jerkson.Json._

scala> val l = List( 
                 Map( "id" -> 1, "name" -> "John" ),
                 Map( "id" -> 2, "name" -> "Dani")
               )

scala> generate( l )

res1: String = [{"id":1,"name":"John"},{"id":2,"name":"Dani"}]

2
Ayrıca, bazı çok zarif ve tür açısından güvenli JSON işlemesi yapabilen vaka sınıfları için gerçekten harika bir desteğe sahiptir .
Thomas Lockney

9
Bu kitaplık yazar tarafından terk edilmiş, başka bir alternatif var mı?
zjffdu

1
"G / Ç, kriptografi ve JSON ve XML işleme ile çalışma gibi yaygın programlama görevleri için güzel deyimsel Scala API'leri sağlayan bir Scala kitaplıkları ailesi olan" rapture.io'yu unutmayalım .
Piohen

12

Listedeki 7 numara Jackson, Jerkson kullanmıyor. Scala nesnelerini (vaka sınıfları vb.) Destekler.

Aşağıda onu nasıl kullandığıma dair bir örnek var.

object MyJacksonMapper extends JacksonMapper
val jsonString = MyJacksonMapper.serializeJson(myObject)
val myNewObject = MyJacksonMapper.deserializeJson[MyCaseClass](jsonString)

Bu, işi çok basitleştirir. Ek olarak XmlSerializer ve JAXB Annotations desteği çok kullanışlıdır.

Bu blog yazısı, JAXB Ek Açıklamaları ve Play Framework ile kullanımını açıklamaktadır.

http://krasserm.blogspot.co.uk/2012/02/using-jaxb-for-xml-and-json-apis-in.html

İşte mevcut JacksonMapper'ım.

trait JacksonMapper {

  def jsonSerializer = {
    val m = new ObjectMapper()
    m.registerModule(DefaultScalaModule)
    m
  }

  def xmlSerializer = {
    val m = new XmlMapper()
    m.registerModule(DefaultScalaModule)
    m
  }

  def deserializeJson[T: Manifest](value: String): T = jsonSerializer.readValue(value, typeReference[T])
  def serializeJson(value: Any) = jsonSerializer.writerWithDefaultPrettyPrinter().writeValueAsString(value)
  def deserializeXml[T: Manifest](value: String): T = xmlSerializer.readValue(value, typeReference[T])
  def serializeXml(value: Any) = xmlSerializer.writeValueAsString(value)

  private[this] def typeReference[T: Manifest] = new TypeReference[T] {
    override def getType = typeFromManifest(manifest[T])
  }

  private[this] def typeFromManifest(m: Manifest[_]): Type = {
     if (m.typeArguments.isEmpty) { m.erasure }
     else new ParameterizedType {
       def getRawType = m.erasure

       def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray

       def getOwnerType = null
     }
  }
}   

8

Belki biraz geç kaldım, ama gerçekten json kitaplığını oyun çerçevesinden kullanmayı denemelisiniz. Belgelere bakabilirsiniz . Mevcut 2.1.1 sürümünde, tüm oyun 2 olmadan ayrı olarak kullanamazsınız, bu nedenle bağımlılık şöyle görünecektir:

val typesaferepo  = "TypeSafe Repo" at "http://repo.typesafe.com/typesafe/releases"
val play2 = "play" %% "play" % "2.1.1"

Size her şeyi içeren tüm oyun çerçevesini getirecek.

Ama Typesafe'den adamların onu 2.2 sürümünde ayırma planları olduğunu bildiğim gibi. Yani, 2.2 anlık görüntüden bağımsız bir play-json var .


2
Bilginize: Play'in JSON kitaplığı Typesafe anlık görüntü deposunda zaten mevcut: repo.typesafe.com/typesafe/snapshots/com/typesafe/play/…
Tvaroh

... Eğer ekleyebileceğiniz şöyle .
bluenote10


5

Sen kontrol etmelidir Genson . Sadece çalışıyor ve Scala'daki mevcut alternatiflerin çoğundan çok daha kolay. Hızlıdır, birçok özelliği ve diğer bazı kütüphanelerle (jodatime, json4s DOM api ...) entegrasyonu vardır.

Tüm bunlar, ima gibi gereksiz kodlar, temel durumlar için özel okuyucular / yazarlar, operatörün aşırı yüklenmesi nedeniyle anlaşılmaz API ...

Kullanmak şu kadar kolaydır:

import com.owlike.genson.defaultGenson_

val json = toJson(Person(Some("foo"), 99))
val person = fromJson[Person]("""{"name": "foo", "age": 99}""")

case class Person(name: Option[String], age: Int)

Feragatname: Ben Gensons yazarıyım ama bu objektif olmadığım anlamına gelmiyor :)


Oldukça havalı, utanç verici bir sorunu var github.com/owlike/genson/issues/82
samthebest

5

İşte jsondosya yazma ve ardından okuma işleminin temel bir uygulaması json4s.

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._
import java.io._
import scala.io.Source


object MyObject { def main(args: Array[String]) {

  val myMap = Map("a" -> List(3,4), "b" -> List(7,8))

  // writing a file 
  val jsonString = pretty(render(myMap))

  val pw = new PrintWriter(new File("my_json.json"))
  pw.write(jsonString)
  pw.close()

  // reading a file 
  val myString = Source.fromFile("my_json.json").mkString
  println(myString)

  val myJSON = parse(myString)

  println(myJSON)

  // Converting from JOjbect to plain object
  implicit val formats = DefaultFormats
  val myOldMap = myJSON.extract[Map[String, List[Int]]]

  println(myOldMap)
 }
}

4

Jawn , Scala'da çok esnek bir JSON ayrıştırıcı kitaplığıdır. Ayrıca özel AST'lerin oluşturulmasına da izin verir; AST ile eşleştirmek için ona küçük bir özellik sağlamanız yeterlidir.

Biraz JSON ayrıştırması gerektiren yeni bir proje için harika çalıştı.


4

Cevaplar listesinde Rapture eksik görünüyor. Bu temin edilebilir http://rapture.io/ ve (başka bir şey arasında) yapmanızı sağlar:

  • JSON arka ucunu seçin; bu, zaten bir tane kullanıyorsanız çok yararlıdır (içe aktarmada)
  • Try, Future, Option, Either, vb. ile çalışıp çalışmayacağınıza karar verin (ayrıca içe aktarmada)
  • tek bir kod satırında çok iş yapın.

Rapture örneklerini sayfasından kopyalamak / yapıştırmak istemiyorum. Rapture'ın özellikleriyle ilgili güzel bir sunum SBTB 2014'te Jon Pretty tarafından yapıldı: https://www.youtube.com/watch?v=ka5-OLJgybI


3

@ AlaxDean'ın # 7 cevabı, Argonaut , sbt ve intellij ile hızlı bir şekilde çalışabildiğim tek cevap . Aslında json4s de çok az zaman aldı ama ham AST ile uğraşmak istediğim şey değildi. Yapımın içine tek bir satır ekleyerek argonotu çalıştırdım. St:

libraryDependencies += "io.argonaut" %% "argonaut" % "6.0.1"

Ve sonra JSON alıp alamayacağımı görmek için basit bir test:

package mytest


import scalaz._, Scalaz._
import argonaut._, Argonaut._

object Mytest extends App {

  val requestJson  =
    """
    {
      "userid": "1"
    }
    """.stripMargin

  val updatedJson: Option[Json] = for {
    parsed <- requestJson.parseOption
  } yield ("name", jString("testuser")) ->: parsed

  val obj = updatedJson.get.obj
  printf("Updated user: %s\n", updatedJson.toString())
  printf("obj : %s\n", obj.toString())
  printf("userid: %s\n", obj.get.toMap("userid"))
}

Ve sonra

$ sbt
> run
Updated user: Some({"userid":"1","name":"testuser"})
obj : Some(object[("userid","1"),("name","testuser")])
userid: "1"

Emin aşina olun Seçeneği de boş (boş kasa ben tahmin) için tıpkı değerdir. Argonaut, Scalaz'ı kullanır, bu nedenle sembol \/(bir veya işlem) gibi anlamadığınız bir şey görürseniz, muhtemelen Scalaz'dır.


2

Bunu deneyebilirsiniz: https://github.com/momodi/Json4Scala

Çok basit ve 300'den az satırlık kod içeren tek bir scala dosyası var.

Örnekler var:

test("base") {
    assert(Json.parse("123").asInt == 123)
    assert(Json.parse("-123").asInt == -123)
    assert(Json.parse("111111111111111").asLong == 111111111111111l)
    assert(Json.parse("true").asBoolean == true)
    assert(Json.parse("false").asBoolean == false)
    assert(Json.parse("123.123").asDouble == 123.123)
    assert(Json.parse("\"aaa\"").asString == "aaa")
    assert(Json.parse("\"aaa\"").write() == "\"aaa\"")

    val json = Json.Value(Map("a" -> Array(1,2,3), "b" -> Array(4, 5, 6)))
    assert(json("a")(0).asInt == 1)
    assert(json("b")(1).asInt == 5)
}
test("parse base") {
    val str =
        """
          {"int":-123, "long": 111111111111111, "string":"asdf", "bool_true": true, "foo":"foo", "bool_false": false}
        """
    val json = Json.parse(str)
    assert(json.asMap("int").asInt == -123)
    assert(json.asMap("long").asLong == 111111111111111l)
    assert(json.asMap("string").asString == "asdf")
    assert(json.asMap("bool_true").asBoolean == true)
    assert(json.asMap("bool_false").asBoolean == false)
    println(json.write())
    assert(json.write().length > 0)
}
test("parse obj") {
    val str =
        """
           {"asdf":[1,2,4,{"bbb":"ttt"},432]}
        """
    val json = Json.parse(str)
    assert(json.asMap("asdf").asArray(0).asInt == 1)
    assert(json.asMap("asdf").asArray(3).asMap("bbb").asString == "ttt")
}
test("parse array") {
    val str =
        """
           [1,2,3,4,{"a":[1,2,3]}]
        """
    val json = Json.parse(str)
    assert(json.asArray(0).asInt == 1)
    assert(json(4)("a")(2).asInt == 3)
    assert(json(4)("a")(2).isInt)
    assert(json(4)("a").isArray)
    assert(json(4)("a").isMap == false)
}
test("real") {
    val str = "{\"styles\":[214776380871671808,214783111085424640,214851869216866304,214829406537908224],\"group\":100,\"name\":\"AO4614【金宏达电子】现货库存 质量保证 欢迎购买@\",\"shopgrade\":8,\"price\":0.59,\"shop_id\":60095469,\"C3\":50018869,\"C2\":50024099,\"C1\":50008090,\"imguri\":\"http://img.geilicdn.com/taobao10000177139_425x360.jpg\",\"cag\":50006523,\"soldout\":0,\"C4\":50006523}"
    val json = Json.parse(str)
    println(json.write())
    assert(json.asMap.size > 0)
}

Bunu beğendim - küçük kullanım durumları için mükemmel - herhangi bir kitaplığa gerek yok.
Samik R

2

İç içe geçmiş durum sınıflarını otomatik olarak işleyeceği büyük avantaja sahip uPickle kullanıyorum :

object SerializingApp extends App {

  case class Person(name: String, address: Address)

  case class Address(street: String, town: String, zipCode: String)

  import upickle.default._

  val john = Person("John Doe", Address("Elm Street 1", "Springfield", "ABC123"))

  val johnAsJson = write(john)
  // Prints {"name":"John Doe","address":{"street":"Elm Street 1","town":"Springfield","zipCode":"ABC123"}}
  Console.println(johnAsJson)

  // Parse the JSON back into a Scala object
  Console.println(read[Person](johnAsJson))  
}

build.sbtUPickle'ı kullanmak için bunu ekleyin:

libraryDependencies += "com.lihaoyi" %% "upickle" % "0.4.3"

0

PLAY JSON kitaplığını kullanıyorum, burada tüm çerçeveyi değil, yalnızca JSON kitaplığı için mavn deposunu bulabilirsiniz.

    val json = "com.typesafe.play" %% "play-json" % version
    val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"

Bunların nasıl kullanılacağına dair çok iyi öğreticiler burada mevcuttur:

http://mandubian.com/2012/09/08/unveiling-play-2-dot-1-json-api-part1-jspath-reads-combinators/

http://mandubian.com/2012/10/01/unveiling-play-2-dot-1-json-api-part2-writes-format-combinators/

http://mandubian.com/2012/10/29/unveiling-play-2-dot-1-json-api-part3-json-transformers/


JSON Play yukarıda zaten belirtilmişti.
bluenote10

0

Size JSON sürümünün SON'unu da vereyim :

import nl.typeset.sonofjson._

arr(
  obj(id = 1, name = "John)
  obj(id = 2, name = "Dani)
)

Bunu kullanmayı çok isterim, ancak maven'de olmadığı için bağımlılıklarıma nasıl ekleyeceğimi çözemiyorum.
Jason Wolosonovich

0

Play, JSON ile Play Framework'ten bağımsız olarak ilgilenmek için modülünü yayınladı, Play WS

Bununla ilgili bir blog yazısı hazırladı , http://pedrorijo.com/blog/scala-json/ adresinden kontrol edin.

Vaka sınıflarını ve Play WS'yi (zaten Play Framework'e dahil edilmiştir) kullanarak, basit bir tek satırlık örtük olarak json ve vaka sınıfları arasında dönüştürme yaparsınız.

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)

object User {
  implicit val userJsonFormat = Json.format[User]
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.