read - play json git
¿Qué biblioteca JSON usar en Scala? (15)
Necesito construir una cadena JSON, algo como esto:
[
{ ''id'': 1, ''name'': ''John''},
{ ''id'': 2, ''name'': ''Dani''}
]
val jArray = JsArray();
jArray += (("id", "1"), ("name", "John"))
jArray += (("id", "2"), ("name", "Dani"))
println(jArray.dump)
Necesito poder agregar filas a jArray
, algo así como jArray += ...
¿Cuál es la biblioteca / solución más cercana a esto?
@ # 7 de la respuesta de AlaxDean, Argonaut es el único que pude trabajar rápidamente con sbt e intellij. En realidad, json4s también tomó poco tiempo, pero lidiar con AST en bruto no es lo que yo quería. Conseguí argonaut para trabajar poniendo una sola línea en mi build.st:
libraryDependencies += "io.argonaut" %% "argonaut" % "6.0.1"
Y luego una prueba simple para ver si puedo obtener 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"))
}
Y entonces
$ sbt
> run
Updated user: Some({"userid":"1","name":"testuser"})
obj : Some(object[("userid","1"),("name","testuser")])
userid: "1"
Asegúrese de estar familiarizado con Option que es solo un valor que también puede ser nulo (supongo que no es seguro). Argonaut utiliza Scalaz así que si ves algo que no comprendes como el símbolo //
(una operación) probablemente sea Scalaz.
Aquí hay una implementación básica de escritura y luego de leer el archivo json
usando 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)
}
}
Deberías consultar a Genson . Simplemente funciona y es mucho más fácil de usar que la mayoría de las alternativas existentes en Scala. Es rápido, tiene muchas características e integraciones con algunas otras librerías (jodatime, json4s DOM api ...).
Todo eso sin ningún código de fantasía innecesario como implicits, lectores / escritores personalizados para casos básicos, API ilisible debido a la sobrecarga del operador ...
Usarlo es tan fácil como:
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)
Descargo de responsabilidad: soy autor de Gensons, pero eso no significa que no soy objetivo :)
El arrebatamiento parece faltar en la lista de respuestas. Se puede obtener de http://rapture.io/ y le permite (entre otras cosas):
- seleccione JSON back-end, que es muy útil si ya usa uno (en importación)
- decida si trabaja con Try, Future, Option, Either, etc. (también en importación)
- hacer un montón de trabajo en una sola línea de código.
No quiero copiar / pegar ejemplos de Rapture desde su página. Jon Pretty en SBTB 2014 ofreció una bonita presentación sobre las características de Rapture: https://www.youtube.com/watch?v=ka5-OLJgybI
El número 7 en la lista es Jackson, no usa Jerkson. Tiene soporte para objetos Scala, (clases de casos, etc.).
A continuación se muestra un ejemplo de cómo lo uso.
object MyJacksonMapper extends JacksonMapper
val jsonString = MyJacksonMapper.serializeJson(myObject)
val myNewObject = MyJacksonMapper.deserializeJson[MyCaseClass](jsonString)
Esto lo hace muy simple. Además, el XmlSerializer y el soporte para JAXB Annotations son muy útiles.
Esta publicación de blog describe su uso con las Anotaciones de JAXB y el Marco de juego.
http://krasserm.blogspot.co.uk/2012/02/using-jaxb-for-xml-and-json-apis-in.html
Aquí está mi JacksonMapper actual.
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
}
}
}
Lamentablemente, escribir una biblioteca JSON es la versión de la comunidad Scala de la codificación de una aplicación de lista de tareas pendientes.
Hay una gran variedad de alternativas. Los enumero sin ningún orden en particular, con notas:
- parsing.json.JSON - Advertencia de que esta biblioteca está disponible solo hasta Scala versión 2.9.x (eliminada en las versiones más nuevas)
- spray-json - Extraído del proyecto Spray
- Jerkson ± - Advertencia una buena biblioteca (construida sobre Java Jackson) pero ahora abandona. Si vas a utilizar esto, probablemente sigas el ejemplo del proyecto Scalding y utiliza el tenedor backchat.io
- sjson - Por Debasish Ghosh
- lift-json - Se puede usar por separado del proyecto Lift
- json4s § ± - Una extracción de lift-json, que intenta crear un JSON AST estándar que otras bibliotecas JSON pueden usar. Incluye una implementación respaldada por Jackson
- Argonaut § - Una biblioteca JSON orientada a FP para Scala, de las personas detrás de Scalaz
- play-json ± - Ahora disponible de manera independiente, mira esta respuesta para más detalles
- dijon - Advertencia abandonada. Una biblioteca de JSON de Scala de tipo dinámico
- sonofjson - Biblioteca JSON con el objetivo de una API super simple
- Jawn - Biblioteca JSON de Erik Osheim con la velocidad de Jackson o más rápida
- Rapture JSON ± - un front-end JSON que puede usar 2, 4, 5, 6, 7, 11 o Jackson como back-ends
- circe - tenedor de Argonaut construido en la parte superior de los cats lugar de scalaz
- jsoniter-scala : macros de Scala para la generación en tiempo de compilación de códecs JSON ultrarrápidos
§ = tiene integración de Scalaz, ± = admite interoperabilidad con Jackson JsonNode
En Snowplow utilizamos json4s con el back-end de Jackson; también hemos tenido buenas experiencias con Argonaut.
Lift-json está en la versión 2.6 y funciona realmente bien (y también está muy bien soportado, el mantenedor siempre está listo para corregir cualquier error que los usuarios puedan encontrar. Puede encontrar ejemplos que lo usan en el repositorio de github
El mantenedor (Joni Freeman) siempre está disponible en la lista de correo de Lift . También hay otros usuarios en la lista de correo que son muy útiles también.
Como señala @Alexey, si desea usar la biblioteca con otra versión de Scala, digamos 2.11.x
, cambie scalaVersion
y use %%
siguiente manera:
scalaVersion := "2.11.5"
"net.liftweb" %% "lift-json" % "2.6"
Puede consultar el sitio de liftweb.net para conocer la última versión con el paso del tiempo.
Permítame también darle la versión SON de JSON :
import nl.typeset.sonofjson._
arr(
obj(id = 1, name = "John)
obj(id = 2, name = "Dani)
)
Play lanzó su módulo para tratar con JSON independientemente de Play Framework, Play WS
Hice una publicación de blog sobre eso, échale un vistazo en http://pedrorijo.com/blog/scala-json/
Usando clases de casos, y Play WS (ya incluido en Play Framework), conviene convertir entre json y case classes con un simple liner implícito
case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)
object User {
implicit val userJsonFormat = Json.format[User]
}
Puede intentar esto: https://github.com/momodi/Json4Scala
Es simple, y tiene solo un archivo scala con menos de 300 líneas de código.
Hay muestras:
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)
}
Sugiero usar Jerkson , es compatible con la mayoría de las conversiones de tipo básico:
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"}]
Tal vez he retrasado un poco, pero realmente deberías tratar de usar la biblioteca json desde el marco de juego. Puedes mirar la documentation . En la versión actual 2.1.1 no se puede usar por separado sin toda la reproducción 2, por lo que la dependencia se verá así:
val typesaferepo = "TypeSafe Repo" at "http://repo.typesafe.com/typesafe/releases"
val play2 = "play" %% "play" % "2.1.1"
Te traerá todo el marco de juego con todas las cosas a bordo.
Pero como sé que los chicos de Typesafe tienen un plan para separarlo en la versión 2.2. Entonces, hay play-json independiente de 2.2-snapshot.
Utilizo uPickle que tiene la gran ventaja de que manejará las clases de casos anidados de forma automática:
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))
}
Agregue esto a su build.sbt
para usar uPickle:
libraryDependencies += "com.lihaoyi" %% "upickle" % "0.4.3"
Utilizo la biblioteca PLAY JSON. Puede encontrar el repositorio mavn solo para la biblioteca JSON, no para todo el marco aquí.
val json = "com.typesafe.play" %% "play-json" % version
val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"
Unos buenos tutoriales sobre cómo usarlos están disponibles aquí:
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/
Jawn es una biblioteca de análisis JSON muy flexible en Scala. También permite la generación de AST personalizados; solo necesitas proporcionarle un pequeño rasgo para mapear al AST.
Funcionó muy bien para un proyecto reciente que necesitaba un poco de análisis JSON.