Яку бібліотеку JSON використовувати в Scala? [зачинено]


125

Мені потрібно побудувати рядок JSON, приблизно так:

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

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

Мені потрібно вміти додавати рядки до jArray, щось подібнеjArray += ...

Яка найближча бібліотека / рішення для цього?


Відповіді:


219

На жаль, написання бібліотеки JSON є версією спільноти Scala, що кодує додаток із списку todo.

Альтернативи є досить різноманітні. Я перелічую їх не в конкретному порядку з примітками:

  1. parsing.json.JSON - попередження про те, що ця бібліотека доступна лише до версії Scala 2.9.x (видаляється в нових версіях)
  2. spray-json - витягнутий з проекту Spray
  3. Jerkson ± - попередження про приємну бібліотеку (побудовану на вершині Java Jackson), але тепер залишити програмне забезпечення. Якщо ви збираєтеся використовувати це, ймовірно, слід за прикладом проекту Scalding та використовуйте вилку backchat.io
  4. sjson - Автор Debasish Ghosh
  5. lift-json - може використовуватися окремо від проекту Lift
  6. json4s 💣 § ± - Витяг з lift-json, який намагається створити стандартний JSON AST, який можуть використовувати інші бібліотеки JSON. Включає підтримку Джексона
  7. Argonaut 💣 § - FP-орієнтована бібліотека JSON для Scala, від людей, які стоять за Scalaz
  8. play-json ± - тепер доступний автономний режим, детальну інформацію див. у цій відповіді
  9. dijon - Зручна, безпечна та ефективна бібліотека JSON, використовує jsoniter-scala під кришкою.
  10. sonofjson - бібліотека JSON, спрямована на надзвичайно простий API
  11. Jawn - бібліотека JSON Еріка Осгейма, яка націлена на швидкість Джексона чи швидше
  12. Rapture JSON ± - передній кінець JSON, який може використовувати 2, 4, 5, 6, 7, 11 або Джексона як зворотні
  13. circe 💣 - вилка аргонавта, побудована зверху на котів замість скалаза
  14. jsoniter-scala - макроси Scala для генерації ультра швидких кодеків JSON за час компіляції
  15. jackson-module-scala - Додатковий модуль для Jackson для підтримки типових даних Scala
  16. буре - Ефективний CBOR і JSON (де) сериализация в Scala

💣 = не має виправлених уразливостей безпеки, § = має інтеграцію Scalaz, ± = підтримує взаємодію з Джексоном JsonNode

У снігоочисник ми використовуємо json4s з Джексоном фоновим; ми також мали гарний досвід роботи з Аргонавтом.


8
Це неправда, що lift-json входить до складу більшого проекту LIft, ви можете просто залежати від lift-json, і нічого іншого від проекту Lift не прийде до вашого проекту.
fmpwizard

3
@AlexDean: Що так погано в parsing.json.JSON?
Маттіас Браун

Схоже, play-json вийде в Play 2.2, і ви вже можете використовувати його зараз: mandubian.com/2013/02/21/play-json-stand-alone
Крістіан

2
@BjornTipling - хороший момент, не можна знайти жодної згадки про його застаріле в 2.11. Видалено цей коментар
Алекс Дін

2
У цьому списку слід розмістити jackson-module-scala вгорі, що на сьогоднішній день є найкращим для продуктивності, простоти, технічного обслуговування та підтримки.
lyomi

17

Lift-json працює у версії 2.6, і вона працює дуже добре (а також дуже добре підтримується, сервіс завжди готовий виправити будь-які помилки, які можуть виявити користувачі. Ви можете знайти приклади, використовуючи його у сховищі github

Технічне обслуговування (Джоні Фріман) завжди доступне у списку розсилки Lift . У списку розсилки також є інші користувачі, які також дуже корисні.

Як зазначає @Alexey, якщо ви хочете використовувати бібліотеку з іншою версією Scala, скажіть 2.11.x, змініть scalaVersionта використовуйте %%наступне:

scalaVersion := "2.11.5" 

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

Ви можете перевірити сайт liftweb.net, щоб дізнатись про останню версію з часом.


3
Я також використовую lift-json і можу підтвердити, що це чудова бібліотека. Це робить як аналіз, так і генерування / серіалізацію JSON дуже простим.
Дан Саймон

1
+1 для "net.liftweb"% "lift-json_2.10"% "2.5.1"
Ділан Хогг

2
а для Scala 2.11: "net.liftweb"% "lift-json_2.11"% "2.6-M4"
Олексій

15

Я пропоную використовувати jerkson , він підтримує більшість основних типів перетворень:

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
Він також має надзвичайно чудову підтримку класів корпусів, яка може зробити дуже елегантним та безпечним для управління JSON.
Томас Локні

9
Ця бібліотека закинута автором, чи є альтернатива?
zjffdu

1
Не будемо забувати про rapture.io , який "є сімейством бібліотек Scala, що забезпечує прекрасні ідіоматичні API Scala для загальних завдань програмування, таких як робота з введенням-виведенням, криптографією та обробкою JSON & XML".
Піохен

12

Число 7 у списку - Джексон, не використовуючи Джерксона. Він має підтримку об’єктів Scala (класи класів тощо).

Нижче наведено приклад того, як я ним користуюся.

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

Це робить його дуже простим. Крім того, XmlSerializer та підтримка анотацій JAXB дуже зручна.

Ця публікація в блозі описує його використання з анотаціями JAXB та Play Framework.

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

Ось мій поточний JacksonMapper.

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

Можливо, я трохи пізно запізнився, але ви дійсно повинні спробувати використати бібліотеку json у програмі play. Ви можете подивитися документацію . У поточному випуску 2.1.1 ви не можете окремо використовувати його без усієї гри 2, тому залежність буде виглядати приблизно так:

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

Це принесе вам цілі рамки гри з усіма предметами на борту.

Але, як я знаю, хлопці з Typesafe мають план розділити його у версії 2.2. Отже, є окремий play-json з 2.2-знімка.


2
FYI: Бібліотека JSON Play вже доступна в моментальних знімках repo.typesafe.com/typesafe/snapshots/com/typesafe/play/…
Tvaroh

... які ви можете додати як так .
bluenote10

Він офіційно використовується в навчальному посібнику sbt
serv-inc

5

Ви повинні перевірити Генсона . Це просто працює і набагато простіше у використанні, ніж більшість існуючих альтернатив Scala. Це швидко, має багато можливостей та інтеграції з деякими іншими libs (jodatime, json4s DOM api ...).

Все це без будь-яких фантазійних непотрібних кодів, таких як імпліцити, користувацькі читачі / автори для основних випадків, незрозумілі API через перевантаження оператора ...

Використовувати його так само просто, як:

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)

Відмова: Я автор Gensons, але це не означає, що я не об'єктивний :)


Досить гребля крута, соромно, є один випуск github.com/owlike/genson/isissue/82
samthebest

5

Ось основна реалізація написання та подальшого читання jsonфайлів за допомогою 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

Джаун - це дуже гнучка бібліотека JSON у Скалі. Це також дозволяє створювати власні AST; вам просто потрібно надати йому невелику ознаку для відображення в AST.

Чудово працював для недавнього проекту, який потребував трохи розбору JSON.


4

Схоже, у списку відповідей відсутнє захоплення. Його можна отримати на веб-сайті http://rapture.io/ і дозволяє (серед іншого):

  • виберіть резервний JSON, що дуже корисно, якщо ви вже використовуєте його (при імпорті)
  • вирішіть, чи працюєте ви з "Спробуйте", "Майбутнє", "Опція", "І т.д." тощо (також імпортуйте)
  • зробити багато роботи в одному рядку коду.

Я не хочу копіювати / вставляти приклади захоплення зі своєї сторінки. Гарну презентацію про особливості Rapture представив Джон Pretty на SBTB 2014: https://www.youtube.com/watch?v=ka5-OLJgybI


3

@ Відповідь AlaxDean №7, Argonaut - це єдиний, з ким я зміг швидко працювати з sbt та intellij. Насправді json4s також зайняв мало часу, але мати справу з сирим AST - це не те, чого я хотів. Я змусив аргонавта працювати, ввівши єдиний рядок у свій build.st:

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

А потім простий тест, щоб побачити, чи можу я отримати JSON:

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

І потім

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

Переконайтеся, що ви знайомі з Варіантом, який є лише значенням, яке також може бути нульовим (я думаю, нульовий). Argonaut використовує Scalaz, тому якщо ви бачите щось, чого не розумієте, як символ \/(або операцію), це, ймовірно, Scalaz.


2

Ви можете спробувати це: https://github.com/momodi/Json4Scala

Це просто і має лише один файл масштабування з меншим кодом 300 рядків.

Є зразки:

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

Мені подобається це - відмінно підходить для невеликих випадків використання - не потрібно жодних бібліотек.
Самік R

2

Я використовую uPickle, який має велику перевагу в тому, що він буде обробляти вкладені класи справ автоматично:

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.sbtщоб використовувати uPickle:

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

0

Я використовую бібліотеку PLAY JSON, тут можна знайти mavn repo лише для бібліотеки JSON, а не для всього тут.

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

Дуже хороші підручники про те, як ними користуватися, доступні тут:

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 вже згадувався вище.
bluenote10


0

Play випустила свій модуль для роботи з JSON незалежно від Play Framework, Play WS

Зробив повідомлення про це в блозі, перегляньте це на http://pedrorijo.com/blog/scala-json/

Використовуючи класи класів і Play WS (вже включені в Play Framework), ви конвертуєте регістр між json і класами case з простим однояйцевим імпліцитом

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

object User {
  implicit val userJsonFormat = Json.format[User]
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.